diff options
Diffstat (limited to 'test/web')
36 files changed, 2064 insertions, 696 deletions
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 03f968aaf..7bdad3810 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -239,7 +239,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do          }        } -      assert {:error, {:remote_limit_error, _}} = ActivityPub.insert(data) +      assert {:error, :remote_limit} = ActivityPub.insert(data)      end      test "doesn't drop activities with content being null" do @@ -386,9 +386,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do    end    describe "create activities" do -    test "it reverts create" do -      user = insert(:user) +    setup do +      [user: insert(:user)] +    end +    test "it reverts create", %{user: user} do        with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do          assert {:error, :reverted} =                   ActivityPub.create(%{ @@ -407,9 +409,47 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert Repo.aggregate(Object, :count, :id) == 0      end -    test "removes doubled 'to' recipients" do -      user = insert(:user) +    test "creates activity if expiration is not configured and expires_at is not passed", %{ +      user: user +    } do +      clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false) + +      assert {:ok, _} = +               ActivityPub.create(%{ +                 to: ["user1", "user2"], +                 actor: user, +                 context: "", +                 object: %{ +                   "to" => ["user1", "user2"], +                   "type" => "Note", +                   "content" => "testing" +                 } +               }) +    end + +    test "rejects activity if expires_at present but expiration is not configured", %{user: user} do +      clear_config([Pleroma.Workers.PurgeExpiredActivity, :enabled], false) + +      assert {:error, :expired_activities_disabled} = +               ActivityPub.create(%{ +                 to: ["user1", "user2"], +                 actor: user, +                 context: "", +                 object: %{ +                   "to" => ["user1", "user2"], +                   "type" => "Note", +                   "content" => "testing" +                 }, +                 additional: %{ +                   "expires_at" => DateTime.utc_now() +                 } +               }) + +      assert Repo.aggregate(Activity, :count, :id) == 0 +      assert Repo.aggregate(Object, :count, :id) == 0 +    end +    test "removes doubled 'to' recipients", %{user: user} do        {:ok, activity} =          ActivityPub.create(%{            to: ["user1", "user1", "user2"], @@ -427,9 +467,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert activity.recipients == ["user1", "user2", user.ap_id]      end -    test "increases user note count only for public activities" do -      user = insert(:user) - +    test "increases user note count only for public activities", %{user: user} do        {:ok, _} =          CommonAPI.post(User.get_cached_by_id(user.id), %{            status: "1", @@ -458,8 +496,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert user.note_count == 2      end -    test "increases replies count" do -      user = insert(:user) +    test "increases replies count", %{user: user} do        user2 = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"}) @@ -1773,6 +1810,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do          |> Enum.map(& &1.id)        assert activities_ids == [] + +      activities_ids = +        %{} +        |> Map.put(:reply_visibility, "self") +        |> Map.put(:reply_filtering_user, nil) +        |> ActivityPub.fetch_public_activities() + +      assert activities_ids == []      end      test "home timeline", %{users: %{u1: user}} do @@ -2069,18 +2114,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do    end    describe "global activity expiration" do -    setup do: clear_config([:mrf, :policies]) -      test "creates an activity expiration for local Create activities" do -      Pleroma.Config.put( -        [:mrf, :policies], -        Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy +      clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy) + +      {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"}) +      {:ok, follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"}) + +      assert_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: activity.id}, +        scheduled_at: +          activity.inserted_at +          |> DateTime.from_naive!("Etc/UTC") +          |> Timex.shift(days: 365)        ) -      {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"}) -      {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"}) - -      assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all() +      refute_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: follow.id} +      )      end    end diff --git a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs index f25cf8b12..e7370d4ef 100644 --- a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs +++ b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs @@ -18,11 +18,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do                 "object" => %{"type" => "Note"}               }) -    assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364 +    assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364    end    test "keeps existing `expires_at` if it less than the config setting" do -    expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: 1) +    expires_at = DateTime.utc_now() |> Timex.shift(days: 1)      assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =               ActivityExpirationPolicy.filter(%{ @@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do    end    test "overwrites existing `expires_at` if it greater than the config setting" do -    too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2) +    too_distant_future = DateTime.utc_now() |> Timex.shift(years: 2)      assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =               ActivityExpirationPolicy.filter(%{ @@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do                 "object" => %{"type" => "Note"}               }) -    assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364 +    assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364    end    test "ignores remote activities" do diff --git a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs index 313d59a66..1710c4d2a 100644 --- a/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs +++ b/test/web/activity_pub/mrf/mediaproxy_warming_policy_test.exs @@ -22,6 +22,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do      }    } +  setup do: clear_config([:media_proxy, :enabled], true) +    test "it prefetches media proxy URIs" do      with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do        MediaProxyWarmingPolicy.filter(@message) diff --git a/test/web/activity_pub/object_validators/note_validator_test.exs b/test/web/activity_pub/object_validators/article_note_validator_test.exs index 30c481ffb..cc6dab872 100644 --- a/test/web/activity_pub/object_validators/note_validator_test.exs +++ b/test/web/activity_pub/object_validators/article_note_validator_test.exs @@ -2,10 +2,10 @@  # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do +defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do    use Pleroma.DataCase -  alias Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator    alias Pleroma.Web.ActivityPub.Utils    import Pleroma.Factory @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidatorTest do      end      test "a basic note validates", %{note: note} do -      %{valid?: true} = NoteValidator.cast_and_validate(note) +      %{valid?: true} = ArticleNoteValidator.cast_and_validate(note)      end    end  end diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs index f2a231eaf..210a06563 100644 --- a/test/web/activity_pub/pipeline_test.exs +++ b/test/web/activity_pub/pipeline_test.exs @@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -51,7 +51,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))          refute called(Pleroma.Web.Federator.publish(activity)) @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -93,7 +93,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))          assert_called(Pleroma.Web.Federator.publish(activity)) @@ -109,7 +109,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -131,7 +131,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))        end @@ -148,7 +148,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do          {            Pleroma.Web.ActivityPub.MRF,            [], -          [filter: fn o -> {:ok, o} end] +          [pipeline_filter: fn o, m -> {:ok, o, m} end]          },          {            Pleroma.Web.ActivityPub.ActivityPub, @@ -170,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do                   Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)          assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta)) -        assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity)) +        assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))          assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))          assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))        end diff --git a/test/web/activity_pub/transmogrifier/article_handling_test.exs b/test/web/activity_pub/transmogrifier/article_handling_test.exs new file mode 100644 index 000000000..9b12a470a --- /dev/null +++ b/test/web/activity_pub/transmogrifier/article_handling_test.exs @@ -0,0 +1,75 @@ +# 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.ArticleHandlingTest do +  use Oban.Testing, repo: Pleroma.Repo +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Object.Fetcher +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  test "Pterotype (Wordpress Plugin) Article" do +    Tesla.Mock.mock(fn %{url: "https://wedistribute.org/wp-json/pterotype/v1/actor/-blog"} -> +      %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/wedistribute-user.json")} +    end) + +    data = +      File.read!("test/fixtures/tesla_mock/wedistribute-create-article.json") |> Jason.decode!() + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    object = Object.normalize(data["object"]) + +    assert object.data["name"] == "The end is near: Mastodon plans to drop OStatus support" + +    assert object.data["summary"] == +             "One of the largest platforms in the federated social web is dropping the protocol that it started with." + +    assert object.data["url"] == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/" +  end + +  test "Plume Article" do +    Tesla.Mock.mock(fn +      %{url: "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-article.json") +        } + +      %{url: "https://baptiste.gelez.xyz/@/BaptisteGelez"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/baptiste.gelex.xyz-user.json") +        } +    end) + +    {:ok, object} = +      Fetcher.fetch_object_from_id( +        "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" +      ) + +    assert object.data["name"] == "This Month in Plume: June 2018" + +    assert object.data["url"] == +             "https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/" +  end + +  test "Prismo Article" do +    Tesla.Mock.mock(fn %{url: "https://prismo.news/@mxb"} -> +      %Tesla.Env{ +        status: 200, +        body: File.read!("test/fixtures/tesla_mock/https___prismo.news__mxb.json") +      } +    end) + +    data = File.read!("test/fixtures/prismo-url-map.json") |> Jason.decode!() + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) +    object = Object.normalize(data["object"]) + +    assert object.data["url"] == "https://prismo.news/posts/83" +  end +end diff --git a/test/web/activity_pub/transmogrifier/video_handling_test.exs b/test/web/activity_pub/transmogrifier/video_handling_test.exs new file mode 100644 index 000000000..69c953a2e --- /dev/null +++ b/test/web/activity_pub/transmogrifier/video_handling_test.exs @@ -0,0 +1,93 @@ +# 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.VideoHandlingTest do +  use Oban.Testing, repo: Pleroma.Repo +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Object.Fetcher +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  setup_all do +    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  test "skip converting the content when it is nil" do +    data = +      File.read!("test/fixtures/tesla_mock/framatube.org-video.json") +      |> Jason.decode!() +      |> Kernel.put_in(["object", "content"], nil) + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["content"] == nil +  end + +  test "it converts content of object to html" do +    data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["content"] == +             "<p>Après avoir mené avec un certain succès la campagne « Dégooglisons Internet » en 2014, l’association Framasoft annonce fin 2019 arrêter progressivement un certain nombre de ses services alternatifs aux GAFAM. Pourquoi ?</p><p>Transcription par @aprilorg ici : <a href=\"https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft\">https://www.april.org/deframasoftisons-internet-pierre-yves-gosset-framasoft</a></p>" +  end + +  test "it remaps video URLs as attachments if necessary" do +    {:ok, object} = +      Fetcher.fetch_object_from_id( +        "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" +      ) + +    assert object.data["url"] == +             "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" + +    assert object.data["attachment"] == [ +             %{ +               "type" => "Link", +               "mediaType" => "video/mp4", +               "name" => nil, +               "url" => [ +                 %{ +                   "href" => +                     "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", +                   "mediaType" => "video/mp4", +                   "type" => "Link" +                 } +               ] +             } +           ] + +    data = File.read!("test/fixtures/tesla_mock/framatube.org-video.json") |> Jason.decode!() + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["attachment"] == [ +             %{ +               "type" => "Link", +               "mediaType" => "video/mp4", +               "name" => nil, +               "url" => [ +                 %{ +                   "href" => +                     "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", +                   "mediaType" => "video/mp4", +                   "type" => "Link" +                 } +               ] +             } +           ] + +    assert object.data["url"] == +             "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" +  end +end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 3fa41b0c7..561674f01 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do    alias Pleroma.Activity    alias Pleroma.Object -  alias Pleroma.Object.Fetcher    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User    alias Pleroma.Web.ActivityPub.Transmogrifier @@ -45,15 +44,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert "test" in object.data["tag"]      end -    test "it works for incoming notices with url not being a string (prismo)" do -      data = File.read!("test/fixtures/prismo-url-map.json") |> Poison.decode!() - -      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) -      object = Object.normalize(data["object"]) - -      assert object.data["url"] == "https://prismo.news/posts/83" -    end -      test "it cleans up incoming notices which are not really DMs" do        user = insert(:user)        other_user = insert(:user) @@ -105,7 +95,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        object =          data["object"] -        |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873") +        |> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394")        data = Map.put(data, "object", object)        {:ok, returned_activity} = Transmogrifier.handle_incoming(data) @@ -113,10 +103,11 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert activity =                 Activity.get_create_by_object_ap_id( -                 "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" +                 "https://mstdn.io/users/mayuutann/statuses/99568293732299394"                 ) -      assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" +      assert returned_object.data["inReplyTo"] == +               "https://mstdn.io/users/mayuutann/statuses/99568293732299394"      end      test "it does not fetch reply-to activities beyond max replies depth limit" do @@ -140,8 +131,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                   "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"                 ) -        assert returned_object.data["inReplyToAtomUri"] == -                 "https://shitposter.club/notice/2827873" +        assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873"        end      end @@ -355,83 +345,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)      end -    test "skip converting the content when it is nil" do -      object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" - -      {:ok, object} = Fetcher.fetch_and_contain_remote_object_from_id(object_id) - -      result = -        Pleroma.Web.ActivityPub.Transmogrifier.fix_object(Map.merge(object, %{"content" => nil})) - -      assert result["content"] == nil -    end - -    test "it converts content of object to html" do -      object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" - -      {:ok, %{"content" => content_markdown}} = -        Fetcher.fetch_and_contain_remote_object_from_id(object_id) - -      {:ok, %Pleroma.Object{data: %{"content" => content}} = object} = -        Fetcher.fetch_object_from_id(object_id) - -      assert content_markdown == -               "Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership\n\nTwenty Years in Jail: FreeBSD's Jails, Then and Now\n\nJails started as a limited virtualization system, but over the last two years they've..." - -      assert content == -               "<p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href=\"http://mug.org/membership\">http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ve…</p>" - -      assert object.data["mediaType"] == "text/html" -    end - -    test "it remaps video URLs as attachments if necessary" do -      {:ok, object} = -        Fetcher.fetch_object_from_id( -          "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" -        ) - -      assert object.data["url"] == -               "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" - -      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", -                     "type" => "Link" -                   } -                 ] -               } -             ] - -      {: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", -                     "type" => "Link" -                   } -                 ] -               } -             ] - -      assert object.data["url"] == -               "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" -    end -      test "it accepts Flag activities" do        user = insert(:user)        other_user = insert(:user) @@ -1072,7 +985,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert Transmogrifier.fix_in_reply_to(data) == data      end -    test "returns object with inReplyToAtomUri when denied incoming reply", %{data: data} do +    test "returns object with inReplyTo when denied incoming reply", %{data: data} do        Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)        object_with_reply = @@ -1080,26 +993,22 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)        assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873" -      assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"        object_with_reply =          Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"})        modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)        assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"} -      assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"        object_with_reply =          Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"])        modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)        assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"] -      assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"        object_with_reply = Map.put(data["object"], "inReplyTo", [])        modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)        assert modified_object["inReplyTo"] == [] -      assert modified_object["inReplyToAtomUri"] == ""      end      @tag capture_log: true @@ -1108,19 +1017,17 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do          Map.put(            data["object"],            "inReplyTo", -          "https://shitposter.club/notice/2827873" +          "https://mstdn.io/users/mayuutann/statuses/99568293732299394"          )        Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5)        modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)        assert modified_object["inReplyTo"] == -               "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" - -      assert modified_object["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873" +               "https://mstdn.io/users/mayuutann/statuses/99568293732299394"        assert modified_object["context"] == -               "tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26" +               "tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4"      end    end @@ -1139,75 +1046,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do               }      end -    test "fixes data for video object" do -      object = %{ -        "type" => "Video", -        "url" => [ -          %{ -            "type" => "Link", -            "mimeType" => "video/mp4", -            "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "video/mp4", -            "href" => "https://peertube46fb-ad81-2d4c2d1630e3-240.mp4" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d1630e3" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d16377-42" -          } -        ] -      } - -      assert Transmogrifier.fix_url(object) == %{ -               "attachment" => [ -                 %{ -                   "href" => "https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4", -                   "mimeType" => "video/mp4", -                   "type" => "Link" -                 } -               ], -               "type" => "Video", -               "url" => "https://peertube.-2d4c2d1630e3" -             } -    end - -    test "fixes url for not Video object" do -      object = %{ -        "type" => "Text", -        "url" => [ -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d1630e3" -          }, -          %{ -            "type" => "Link", -            "mimeType" => "text/html", -            "href" => "https://peertube.-2d4c2d16377-42" -          } -        ] -      } - -      assert Transmogrifier.fix_url(object) == %{ -               "type" => "Text", -               "url" => "https://peertube.-2d4c2d1630e3" -             } - -      assert Transmogrifier.fix_url(%{"type" => "Text", "url" => []}) == %{ -               "type" => "Text", -               "url" => "" -             } -    end - -    test "retunrs not modified object" do +    test "returns non-modified object" do        assert Transmogrifier.fix_url(%{"type" => "Text"}) == %{"type" => "Text"}      end    end @@ -1222,7 +1061,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do      @tag capture_log: true      test "returns {:ok, %Object{}} for success case" do        assert {:ok, %Object{}} = -               Transmogrifier.get_obj_helper("https://shitposter.club/notice/2827873") +               Transmogrifier.get_obj_helper( +                 "https://mstdn.io/users/mayuutann/statuses/99568293732299394" +               )      end    end diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index 3bc88c6a9..e4d3512de 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -1510,6 +1510,56 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do      end    end +  describe "GET /api/pleroma/admin/users/:nickname/chats" do +    setup do +      user = insert(:user) +      recipients = insert_list(3, :user) + +      Enum.each(recipients, fn recipient -> +        CommonAPI.post_chat_message(user, recipient, "yo") +      end) + +      %{user: user} +    end + +    test "renders user's chats", %{conn: conn, user: user} do +      conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats") + +      assert json_response(conn, 200) |> length() == 3 +    end +  end + +  describe "GET /api/pleroma/admin/users/:nickname/chats unauthorized" do +    setup do +      user = insert(:user) +      recipient = insert(:user) +      CommonAPI.post_chat_message(user, recipient, "yo") +      %{conn: conn} = oauth_access(["read:chats"]) +      %{conn: conn, user: user} +    end + +    test "returns 403", %{conn: conn, user: user} do +      conn +      |> get("/api/pleroma/admin/users/#{user.nickname}/chats") +      |> json_response(403) +    end +  end + +  describe "GET /api/pleroma/admin/users/:nickname/chats unauthenticated" do +    setup do +      user = insert(:user) +      recipient = insert(:user) +      CommonAPI.post_chat_message(user, recipient, "yo") +      %{conn: build_conn(), user: user} +    end + +    test "returns 403", %{conn: conn, user: user} do +      conn +      |> get("/api/pleroma/admin/users/#{user.nickname}/chats") +      |> json_response(403) +    end +  end +    describe "GET /api/pleroma/admin/moderation_log" do      setup do        moderator = insert(:user, is_moderator: true) diff --git a/test/web/admin_api/controllers/chat_controller_test.exs b/test/web/admin_api/controllers/chat_controller_test.exs new file mode 100644 index 000000000..bd4c9c9d1 --- /dev/null +++ b/test/web/admin_api/controllers/chat_controller_test.exs @@ -0,0 +1,219 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.ChatControllerTest do +  use Pleroma.Web.ConnCase + +  import Pleroma.Factory + +  alias Pleroma.Chat +  alias Pleroma.Chat.MessageReference +  alias Pleroma.Config +  alias Pleroma.ModerationLog +  alias Pleroma.Object +  alias Pleroma.Repo +  alias Pleroma.Web.CommonAPI + +  defp admin_setup do +    admin = insert(:user, is_admin: true) +    token = insert(:oauth_admin_token, user: admin) + +    conn = +      build_conn() +      |> assign(:user, admin) +      |> assign(:token, token) + +    {:ok, %{admin: admin, token: token, conn: conn}} +  end + +  describe "DELETE /api/pleroma/admin/chats/:id/messages/:message_id" do +    setup do: admin_setup() + +    test "it deletes a message from the chat", %{conn: conn, admin: admin} do +      user = insert(:user) +      recipient = insert(:user) + +      {:ok, message} = +        CommonAPI.post_chat_message(user, recipient, "Hello darkness my old friend") + +      object = Object.normalize(message, false) + +      chat = Chat.get(user.id, recipient.ap_id) +      recipient_chat = Chat.get(recipient.id, user.ap_id) + +      cm_ref = MessageReference.for_chat_and_object(chat, object) +      recipient_cm_ref = MessageReference.for_chat_and_object(recipient_chat, object) + +      result = +        conn +        |> put_req_header("content-type", "application/json") +        |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") +        |> json_response_and_validate_schema(200) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} deleted chat message ##{cm_ref.id}" + +      assert result["id"] == cm_ref.id +      refute MessageReference.get_by_id(cm_ref.id) +      refute MessageReference.get_by_id(recipient_cm_ref.id) +      assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id) +    end +  end + +  describe "GET /api/pleroma/admin/chats/:id/messages" do +    setup do: admin_setup() + +    test "it paginates", %{conn: conn} do +      user = insert(:user) +      recipient = insert(:user) + +      Enum.each(1..30, fn _ -> +        {:ok, _} = CommonAPI.post_chat_message(user, recipient, "hey") +      end) + +      chat = Chat.get(user.id, recipient.ap_id) + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +        |> json_response_and_validate_schema(200) + +      assert length(result) == 20 + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") +        |> json_response_and_validate_schema(200) + +      assert length(result) == 10 +    end + +    test "it returns the messages for a given chat", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) +      third_user = insert(:user) + +      {:ok, _} = CommonAPI.post_chat_message(user, other_user, "hey") +      {:ok, _} = CommonAPI.post_chat_message(user, third_user, "hey") +      {:ok, _} = CommonAPI.post_chat_message(user, other_user, "how are you?") +      {:ok, _} = CommonAPI.post_chat_message(other_user, user, "fine, how about you?") + +      chat = Chat.get(user.id, other_user.ap_id) + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +        |> json_response_and_validate_schema(200) + +      result +      |> Enum.each(fn message -> +        assert message["chat_id"] == chat.id |> to_string() +      end) + +      assert length(result) == 3 +    end +  end + +  describe "GET /api/pleroma/admin/chats/:id" do +    setup do: admin_setup() + +    test "it returns a chat", %{conn: conn} do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + +      result = +        conn +        |> get("/api/pleroma/admin/chats/#{chat.id}") +        |> json_response_and_validate_schema(200) + +      assert result["id"] == to_string(chat.id) +      assert %{} = result["sender"] +      assert %{} = result["receiver"] +      refute result["account"] +    end +  end + +  describe "unauthorized chat moderation" do +    setup do +      user = insert(:user) +      recipient = insert(:user) + +      {:ok, message} = CommonAPI.post_chat_message(user, recipient, "Yo") +      object = Object.normalize(message, false) +      chat = Chat.get(user.id, recipient.ap_id) +      cm_ref = MessageReference.for_chat_and_object(chat, object) + +      %{conn: conn} = oauth_access(["read:chats", "write:chats"]) +      %{conn: conn, chat: chat, cm_ref: cm_ref} +    end + +    test "DELETE /api/pleroma/admin/chats/:id/messages/:message_id", %{ +      conn: conn, +      chat: chat, +      cm_ref: cm_ref +    } do +      conn +      |> put_req_header("content-type", "application/json") +      |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") +      |> json_response(403) + +      assert MessageReference.get_by_id(cm_ref.id) == cm_ref +    end + +    test "GET /api/pleroma/admin/chats/:id/messages", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +      |> json_response(403) +    end + +    test "GET /api/pleroma/admin/chats/:id", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}") +      |> json_response(403) +    end +  end + +  describe "unauthenticated chat moderation" do +    setup do +      user = insert(:user) +      recipient = insert(:user) + +      {:ok, message} = CommonAPI.post_chat_message(user, recipient, "Yo") +      object = Object.normalize(message, false) +      chat = Chat.get(user.id, recipient.ap_id) +      cm_ref = MessageReference.for_chat_and_object(chat, object) + +      %{conn: build_conn(), chat: chat, cm_ref: cm_ref} +    end + +    test "DELETE /api/pleroma/admin/chats/:id/messages/:message_id", %{ +      conn: conn, +      chat: chat, +      cm_ref: cm_ref +    } do +      conn +      |> put_req_header("content-type", "application/json") +      |> delete("/api/pleroma/admin/chats/#{chat.id}/messages/#{cm_ref.id}") +      |> json_response(403) + +      assert MessageReference.get_by_id(cm_ref.id) == cm_ref +    end + +    test "GET /api/pleroma/admin/chats/:id/messages", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}/messages") +      |> json_response(403) +    end + +    test "GET /api/pleroma/admin/chats/:id", %{conn: conn, chat: chat} do +      conn +      |> get("/api/pleroma/admin/chats/#{chat.id}") +      |> json_response(403) +    end +  end +end diff --git a/test/web/admin_api/controllers/instance_document_controller_test.exs b/test/web/admin_api/controllers/instance_document_controller_test.exs new file mode 100644 index 000000000..5f7b042f6 --- /dev/null +++ b/test/web/admin_api/controllers/instance_document_controller_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.AdminAPI.InstanceDocumentControllerTest do +  use Pleroma.Web.ConnCase, async: true +  import Pleroma.Factory +  alias Pleroma.Config + +  @dir "test/tmp/instance_static" +  @default_instance_panel ~s(<p>Welcome to <a href="https://pleroma.social" target="_blank">Pleroma!</a></p>) + +  setup do +    File.mkdir_p!(@dir) +    on_exit(fn -> File.rm_rf(@dir) end) +  end + +  setup do: clear_config([:instance, :static_dir], @dir) + +  setup do +    admin = insert(:user, is_admin: true) +    token = insert(:oauth_admin_token, user: admin) + +    conn = +      build_conn() +      |> assign(:user, admin) +      |> assign(:token, token) + +    {:ok, %{admin: admin, token: token, conn: conn}} +  end + +  describe "GET /api/pleroma/admin/instance_document/:name" do +    test "return the instance document url", %{conn: conn} do +      conn = get(conn, "/api/pleroma/admin/instance_document/instance-panel") + +      assert content = html_response(conn, 200) +      assert String.contains?(content, @default_instance_panel) +    end + +    test "it returns 403 if requested by a non-admin" do +      non_admin_user = insert(:user) +      token = insert(:oauth_token, user: non_admin_user) + +      conn = +        build_conn() +        |> assign(:user, non_admin_user) +        |> assign(:token, token) +        |> get("/api/pleroma/admin/instance_document/instance-panel") + +      assert json_response(conn, :forbidden) +    end + +    test "it returns 404 if the instance document with the given name doesn't exist", %{ +      conn: conn +    } do +      conn = get(conn, "/api/pleroma/admin/instance_document/1234") + +      assert json_response_and_validate_schema(conn, 404) +    end +  end + +  describe "PATCH /api/pleroma/admin/instance_document/:name" do +    test "uploads the instance document", %{conn: conn} do +      image = %Plug.Upload{ +        content_type: "text/html", +        path: Path.absname("test/fixtures/custom_instance_panel.html"), +        filename: "custom_instance_panel.html" +      } + +      conn = +        conn +        |> put_req_header("content-type", "multipart/form-data") +        |> patch("/api/pleroma/admin/instance_document/instance-panel", %{ +          "file" => image +        }) + +      assert %{"url" => url} = json_response_and_validate_schema(conn, 200) +      index = get(build_conn(), url) +      assert html_response(index, 200) == "<h2>Custom instance panel</h2>" +    end +  end + +  describe "DELETE /api/pleroma/admin/instance_document/:name" do +    test "deletes the instance document", %{conn: conn} do +      File.mkdir!(@dir <> "/instance/") +      File.write!(@dir <> "/instance/panel.html", "Custom instance panel") + +      conn_resp = +        conn +        |> get("/api/pleroma/admin/instance_document/instance-panel") + +      assert html_response(conn_resp, 200) == "Custom instance panel" + +      conn +      |> delete("/api/pleroma/admin/instance_document/instance-panel") +      |> json_response_and_validate_schema(200) + +      conn_resp = +        conn +        |> get("/api/pleroma/admin/instance_document/instance-panel") + +      assert content = html_response(conn_resp, 200) +      assert String.contains?(content, @default_instance_panel) +    end +  end +end diff --git a/test/web/admin_api/search_test.exs b/test/web/admin_api/search_test.exs index b974cedd5..d88867c52 100644 --- a/test/web/admin_api/search_test.exs +++ b/test/web/admin_api/search_test.exs @@ -177,5 +177,14 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do        assert total == 3        assert count == 1      end + +    test "it returns non-discoverable users" do +      insert(:user) +      insert(:user, discoverable: false) + +      {:ok, _results, total} = Search.user() + +      assert total == 2 +    end    end  end diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 800db9a20..2eab64e8b 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -4,6 +4,8 @@  defmodule Pleroma.Web.CommonAPITest do    use Pleroma.DataCase +  use Oban.Testing, repo: Pleroma.Repo +    alias Pleroma.Activity    alias Pleroma.Chat    alias Pleroma.Conversation.Participation @@ -215,6 +217,17 @@ defmodule Pleroma.Web.CommonAPITest do        assert message == :content_too_long      end + +    test "it reject messages via MRF" do +      clear_config([:mrf_keyword, :reject], ["GNO"]) +      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + +      author = insert(:user) +      recipient = insert(:user) + +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +               CommonAPI.post_chat_message(author, recipient, "GNO/Linux") +    end    end    describe "unblocking" do @@ -598,15 +611,15 @@ defmodule Pleroma.Web.CommonAPITest do      test "it can handle activities that expire" do        user = insert(:user) -      expires_at = -        NaiveDateTime.utc_now() -        |> NaiveDateTime.truncate(:second) -        |> NaiveDateTime.add(1_000_000, :second) +      expires_at = DateTime.add(DateTime.utc_now(), 1_000_000)        assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000}) -      assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id) -      assert expiration.scheduled_at == expires_at +      assert_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: activity.id}, +        scheduled_at: expires_at +      )      end    end @@ -1191,4 +1204,24 @@ defmodule Pleroma.Web.CommonAPITest do        assert Visibility.get_visibility(activity) == "private"      end    end + +  describe "get_user/1" do +    test "gets user by ap_id" do +      user = insert(:user) +      assert CommonAPI.get_user(user.ap_id) == user +    end + +    test "gets user by guessed nickname" do +      user = insert(:user, ap_id: "", nickname: "mario@mushroom.kingdom") +      assert CommonAPI.get_user("https://mushroom.kingdom/users/mario") == user +    end + +    test "fallback" do +      assert %User{ +               name: "", +               ap_id: "", +               nickname: "erroruser@example.com" +             } = CommonAPI.get_user("") +    end +  end  end diff --git a/test/web/fed_sockets/fed_registry_test.exs b/test/web/fed_sockets/fed_registry_test.exs new file mode 100644 index 000000000..19ac874d6 --- /dev/null +++ b/test/web/fed_sockets/fed_registry_test.exs @@ -0,0 +1,124 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FedRegistryTest do +  use ExUnit.Case + +  alias Pleroma.Web.FedSockets +  alias Pleroma.Web.FedSockets.FedRegistry +  alias Pleroma.Web.FedSockets.SocketInfo + +  @good_domain "http://good.domain" +  @good_domain_origin "good.domain:80" + +  setup do +    start_supervised({Pleroma.Web.FedSockets.Supervisor, []}) +    build_test_socket(@good_domain) +    Process.sleep(10) + +    :ok +  end + +  describe "add_fed_socket/1 without conflicting sockets" do +    test "can be added" do +      Process.sleep(10) +      assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin) +      assert origin == "good.domain:80" +    end + +    test "multiple origins can be added" do +      build_test_socket("http://anothergood.domain") +      Process.sleep(10) + +      assert {:ok, %SocketInfo{origin: origin_1}} = +               FedRegistry.get_fed_socket(@good_domain_origin) + +      assert {:ok, %SocketInfo{origin: origin_2}} = +               FedRegistry.get_fed_socket("anothergood.domain:80") + +      assert origin_1 == "good.domain:80" +      assert origin_2 == "anothergood.domain:80" +      assert FedRegistry.list_all() |> Enum.count() == 2 +    end +  end + +  describe "add_fed_socket/1 when duplicate sockets conflict" do +    setup do +      build_test_socket(@good_domain) +      build_test_socket(@good_domain) +      Process.sleep(10) +      :ok +    end + +    test "will be ignored" do +      assert {:ok, %SocketInfo{origin: origin, pid: pid_one}} = +               FedRegistry.get_fed_socket(@good_domain_origin) + +      assert origin == "good.domain:80" + +      assert FedRegistry.list_all() |> Enum.count() == 1 +    end + +    test "the newer process will be closed" do +      pid_two = build_test_socket(@good_domain) + +      assert {:ok, %SocketInfo{origin: origin, pid: pid_one}} = +               FedRegistry.get_fed_socket(@good_domain_origin) + +      assert origin == "good.domain:80" +      Process.sleep(10) + +      refute Process.alive?(pid_two) + +      assert FedRegistry.list_all() |> Enum.count() == 1 +    end +  end + +  describe "get_fed_socket/1" do +    test "returns missing for unknown hosts" do +      assert {:error, :missing} = FedRegistry.get_fed_socket("not_a_dmoain") +    end + +    test "returns rejected for hosts previously rejected" do +      "rejected.domain:80" +      |> FedSockets.uri_for_origin() +      |> FedRegistry.set_host_rejected() + +      assert {:error, :rejected} = FedRegistry.get_fed_socket("rejected.domain:80") +    end + +    test "can retrieve a previously added SocketInfo" do +      build_test_socket(@good_domain) +      Process.sleep(10) +      assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin) +      assert origin == "good.domain:80" +    end + +    test "removes references to SocketInfos when the process crashes" do +      assert {:ok, %SocketInfo{origin: origin, pid: pid}} = +               FedRegistry.get_fed_socket(@good_domain_origin) + +      assert origin == "good.domain:80" + +      Process.exit(pid, :testing) +      Process.sleep(100) +      assert {:error, :missing} = FedRegistry.get_fed_socket(@good_domain_origin) +    end +  end + +  def build_test_socket(uri) do +    Kernel.spawn(fn -> fed_socket_almost(uri) end) +  end + +  def fed_socket_almost(origin) do +    FedRegistry.add_fed_socket(origin) + +    receive do +      :close -> +        :ok +    after +      5_000 -> :timeout +    end +  end +end diff --git a/test/web/fed_sockets/fetch_registry_test.exs b/test/web/fed_sockets/fetch_registry_test.exs new file mode 100644 index 000000000..7bd2d995a --- /dev/null +++ b/test/web/fed_sockets/fetch_registry_test.exs @@ -0,0 +1,67 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.FetchRegistryTest do +  use ExUnit.Case + +  alias Pleroma.Web.FedSockets.FetchRegistry +  alias Pleroma.Web.FedSockets.FetchRegistry.FetchRegistryData + +  @json_message "hello" +  @json_reply "hello back" + +  setup do +    start_supervised( +      {Pleroma.Web.FedSockets.Supervisor, +       [ +         ping_interval: 8, +         connection_duration: 15, +         rejection_duration: 5, +         fed_socket_fetches: [default: 10, interval: 10] +       ]} +    ) + +    :ok +  end + +  test "fetches can be stored" do +    uuid = FetchRegistry.register_fetch(@json_message) + +    assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) +  end + +  test "fetches can return" do +    uuid = FetchRegistry.register_fetch(@json_message) +    task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end) + +    assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) +    Task.await(task) + +    assert {:ok, %FetchRegistryData{received_json: received_json}} = +             FetchRegistry.check_fetch(uuid) + +    assert received_json == @json_reply +  end + +  test "fetches are deleted once popped from stack" do +    uuid = FetchRegistry.register_fetch(@json_message) +    task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end) +    Task.await(task) + +    assert {:ok, %FetchRegistryData{received_json: received_json}} = +             FetchRegistry.check_fetch(uuid) + +    assert received_json == @json_reply +    assert {:ok, @json_reply} = FetchRegistry.pop_fetch(uuid) + +    assert {:error, :missing} = FetchRegistry.check_fetch(uuid) +  end + +  test "fetches can time out" do +    uuid = FetchRegistry.register_fetch(@json_message) +    assert {:error, :waiting} = FetchRegistry.check_fetch(uuid) +    Process.sleep(500) +    assert {:error, :missing} = FetchRegistry.check_fetch(uuid) +  end +end diff --git a/test/web/fed_sockets/socket_info_test.exs b/test/web/fed_sockets/socket_info_test.exs new file mode 100644 index 000000000..db3d6edcd --- /dev/null +++ b/test/web/fed_sockets/socket_info_test.exs @@ -0,0 +1,118 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.FedSockets.SocketInfoTest do +  use ExUnit.Case + +  alias Pleroma.Web.FedSockets +  alias Pleroma.Web.FedSockets.SocketInfo + +  describe "uri_for_origin" do +    test "provides the fed_socket URL given the origin information" do +      endpoint = "example.com:4000" +      assert FedSockets.uri_for_origin(endpoint) =~ "ws://" +      assert FedSockets.uri_for_origin(endpoint) =~ endpoint +    end +  end + +  describe "origin" do +    test "will provide the origin field given a url" do +      endpoint = "example.com:4000" +      assert SocketInfo.origin("ws://#{endpoint}") == endpoint +      assert SocketInfo.origin("http://#{endpoint}") == endpoint +      assert SocketInfo.origin("https://#{endpoint}") == endpoint +    end + +    test "will proide the origin field given a uri" do +      endpoint = "example.com:4000" +      uri = URI.parse("http://#{endpoint}") + +      assert SocketInfo.origin(uri) == endpoint +    end +  end + +  describe "touch" do +    test "will update the TTL" do +      endpoint = "example.com:4000" +      socket = SocketInfo.build("ws://#{endpoint}") +      Process.sleep(2) +      touched_socket = SocketInfo.touch(socket) + +      assert socket.connected_until < touched_socket.connected_until +    end +  end + +  describe "expired?" do +    setup do +      start_supervised( +        {Pleroma.Web.FedSockets.Supervisor, +         [ +           ping_interval: 8, +           connection_duration: 5, +           rejection_duration: 5, +           fed_socket_rejections: [lazy: true] +         ]} +      ) + +      :ok +    end + +    test "tests if the TTL is exceeded" do +      endpoint = "example.com:4000" +      socket = SocketInfo.build("ws://#{endpoint}") +      refute SocketInfo.expired?(socket) +      Process.sleep(10) + +      assert SocketInfo.expired?(socket) +    end +  end + +  describe "creating outgoing connection records" do +    test "can be passed a string" do +      assert %{conn_pid: :pid, origin: _origin} = SocketInfo.build("example.com:4000", :pid) +    end + +    test "can be passed a URI" do +      uri = URI.parse("http://example.com:4000") +      assert %{conn_pid: :pid, origin: origin} = SocketInfo.build(uri, :pid) +      assert origin =~ "example.com:4000" +    end + +    test "will include the port number" do +      assert %{conn_pid: :pid, origin: origin} = SocketInfo.build("http://example.com:4000", :pid) + +      assert origin =~ ":4000" +    end + +    test "will provide the port if missing" do +      assert %{conn_pid: :pid, origin: "example.com:80"} = +               SocketInfo.build("http://example.com", :pid) + +      assert %{conn_pid: :pid, origin: "example.com:443"} = +               SocketInfo.build("https://example.com", :pid) +    end +  end + +  describe "creating incoming connection records" do +    test "can be passed a string" do +      assert %{pid: _, origin: _origin} = SocketInfo.build("example.com:4000") +    end + +    test "can be passed a URI" do +      uri = URI.parse("example.com:4000") +      assert %{pid: _, origin: _origin} = SocketInfo.build(uri) +    end + +    test "will include the port number" do +      assert %{pid: _, origin: origin} = SocketInfo.build("http://example.com:4000") + +      assert origin =~ ":4000" +    end + +    test "will provide the port if missing" do +      assert %{pid: _, origin: "example.com:80"} = SocketInfo.build("http://example.com") +      assert %{pid: _, origin: "example.com:443"} = SocketInfo.build("https://example.com") +    end +  end +end diff --git a/test/web/instances/instance_test.exs b/test/web/instances/instance_test.exs index dc6ace843..4f0805100 100644 --- a/test/web/instances/instance_test.exs +++ b/test/web/instances/instance_test.exs @@ -99,35 +99,54 @@ defmodule Pleroma.Instances.InstanceTest do      end    end -  test "Scrapes favicon URLs" do -    Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} -> -      %Tesla.Env{ -        status: 200, -        body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>] -      } -    end) - -    assert "https://favicon.example.org/favicon.png" == -             Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/")) -  end +  describe "get_or_update_favicon/1" do +    test "Scrapes favicon URLs" do +      Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} -> +        %Tesla.Env{ +          status: 200, +          body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>] +        } +      end) + +      assert "https://favicon.example.org/favicon.png" == +               Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/")) +    end -  test "Returns nil on too long favicon URLs" do -    long_favicon_url = -      "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png" - -    Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} -> -      %Tesla.Env{ -        status: 200, -        body: ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>] -      } -    end) - -    assert capture_log(fn -> -             assert nil == -                      Instance.get_or_update_favicon( -                        URI.parse("https://long-favicon.example.org/") -                      ) -           end) =~ -             "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{" +    test "Returns nil on too long favicon URLs" do +      long_favicon_url = +        "https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png" + +      Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} -> +        %Tesla.Env{ +          status: 200, +          body: +            ~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>] +        } +      end) + +      assert capture_log(fn -> +               assert nil == +                        Instance.get_or_update_favicon( +                          URI.parse("https://long-favicon.example.org/") +                        ) +             end) =~ +               "Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{" +    end + +    test "Handles not getting a favicon URL properly" do +      Tesla.Mock.mock(fn %{url: "https://no-favicon.example.org/"} -> +        %Tesla.Env{ +          status: 200, +          body: ~s[<html><head><h1>I wil look down and whisper "GNO.."</h1></head></html>] +        } +      end) + +      refute capture_log(fn -> +               assert nil == +                        Instance.get_or_update_favicon( +                          URI.parse("https://no-favicon.example.org/") +                        ) +             end) =~ "Instance.scrape_favicon(\"https://no-favicon.example.org/\") error: " +    end    end  end diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 17a1e7d66..f7f1369e4 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -1442,7 +1442,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do    describe "verify_credentials" do      test "verify_credentials" do        %{user: user, conn: conn} = oauth_access(["read:accounts"]) -      [notification | _] = insert_list(7, :notification, user: user) + +      [notification | _] = +        insert_list(7, :notification, user: user, activity: insert(:note_activity)) +        Pleroma.Notification.set_read_up_to(user, notification.id)        conn = get(conn, "/api/v1/accounts/verify_credentials") diff --git a/test/web/mastodon_api/controllers/marker_controller_test.exs b/test/web/mastodon_api/controllers/marker_controller_test.exs index 6dd40fb4a..9f0481120 100644 --- a/test/web/mastodon_api/controllers/marker_controller_test.exs +++ b/test/web/mastodon_api/controllers/marker_controller_test.exs @@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do      test "gets markers with correct scopes", %{conn: conn} do        user = insert(:user)        token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) -      insert_list(7, :notification, user: user) +      insert_list(7, :notification, user: user, activity: insert(:note_activity))        {:ok, %{"notifications" => marker}} =          Pleroma.Marker.upsert( diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs index 24d1959f8..04dc6f445 100644 --- a/test/web/mastodon_api/controllers/search_controller_test.exs +++ b/test/web/mastodon_api/controllers/search_controller_test.exs @@ -282,18 +282,18 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do        capture_log(fn ->          {:ok, %{id: activity_id}} =            CommonAPI.post(insert(:user), %{ -            status: "check out https://shitposter.club/notice/2827873" +            status: "check out http://mastodon.example.org/@admin/99541947525187367"            })          results =            conn -          |> get("/api/v1/search?q=https://shitposter.club/notice/2827873") +          |> get("/api/v1/search?q=http://mastodon.example.org/@admin/99541947525187367")            |> json_response_and_validate_schema(200) -        [status, %{"id" => ^activity_id}] = results["statuses"] - -        assert status["uri"] == -                 "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" +        assert [ +                 %{"url" => "http://mastodon.example.org/@admin/99541947525187367"}, +                 %{"id" => ^activity_id} +               ] = results["statuses"]        end)      end diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index f221884e7..633a25e50 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -4,9 +4,9 @@  defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do    use Pleroma.Web.ConnCase +  use Oban.Testing, repo: Pleroma.Repo    alias Pleroma.Activity -  alias Pleroma.ActivityExpiration    alias Pleroma.Config    alias Pleroma.Conversation.Participation    alias Pleroma.Object @@ -29,8 +29,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      setup do: oauth_access(["write:statuses"])      test "posting a status does not increment reblog_count when relaying", %{conn: conn} do -      Pleroma.Config.put([:instance, :federating], true) -      Pleroma.Config.get([:instance, :allow_relay], true) +      Config.put([:instance, :federating], true) +      Config.get([:instance, :allow_relay], true)        response =          conn @@ -103,7 +103,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do        # An activity that will expire:        # 2 hours -      expires_in = 120 * 60 +      expires_in = 2 * 60 * 60 + +      expires_at = DateTime.add(DateTime.utc_now(), expires_in)        conn_four =          conn @@ -113,29 +115,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do            "expires_in" => expires_in          }) -      assert fourth_response = -               %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200) - -      assert activity = Activity.get_by_id(fourth_id) -      assert expiration = ActivityExpiration.get_by_activity_id(fourth_id) - -      estimated_expires_at = -        NaiveDateTime.utc_now() -        |> NaiveDateTime.add(expires_in) -        |> NaiveDateTime.truncate(:second) +      assert %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200) -      # This assert will fail if the test takes longer than a minute. I sure hope it never does: -      assert abs(NaiveDateTime.diff(expiration.scheduled_at, estimated_expires_at, :second)) < 60 +      assert Activity.get_by_id(fourth_id) -      assert fourth_response["pleroma"]["expires_at"] == -               NaiveDateTime.to_iso8601(expiration.scheduled_at) +      assert_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: fourth_id}, +        scheduled_at: expires_at +      )      end      test "it fails to create a status if `expires_in` is less or equal than an hour", %{        conn: conn      } do -      # 1 hour -      expires_in = 60 * 60 +      # 1 minute +      expires_in = 1 * 60        assert %{"error" => "Expiry date is too soon"} =                 conn @@ -146,8 +141,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do                 })                 |> json_response_and_validate_schema(422) -      # 30 minutes -      expires_in = 30 * 60 +      # 5 minutes +      expires_in = 5 * 60        assert %{"error" => "Expiry date is too soon"} =                 conn @@ -160,8 +155,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do      end      test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do -      Pleroma.Config.put([:mrf_keyword, :reject], ["GNO"]) -      Pleroma.Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) +      Config.put([:mrf_keyword, :reject], ["GNO"]) +      Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])        assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} =                 conn @@ -1146,6 +1141,52 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do                 |> post("/api/v1/statuses/#{activity_two.id}/pin")                 |> json_response_and_validate_schema(400)      end + +    test "on pin removes deletion job, on unpin reschedule deletion" do +      %{conn: conn} = oauth_access(["write:accounts", "write:statuses"]) +      expires_in = 2 * 60 * 60 + +      expires_at = DateTime.add(DateTime.utc_now(), expires_in) + +      assert %{"id" => id} = +               conn +               |> put_req_header("content-type", "application/json") +               |> post("api/v1/statuses", %{ +                 "status" => "oolong", +                 "expires_in" => expires_in +               }) +               |> json_response_and_validate_schema(200) + +      assert_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: id}, +        scheduled_at: expires_at +      ) + +      assert %{"id" => ^id, "pinned" => true} = +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/v1/statuses/#{id}/pin") +               |> json_response_and_validate_schema(200) + +      refute_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: id}, +        scheduled_at: expires_at +      ) + +      assert %{"id" => ^id, "pinned" => false} = +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/v1/statuses/#{id}/unpin") +               |> json_response_and_validate_schema(200) + +      assert_enqueued( +        worker: Pleroma.Workers.PurgeExpiredActivity, +        args: %{activity_id: id}, +        scheduled_at: expires_at +      ) +    end    end    describe "cards" do @@ -1681,19 +1722,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do    test "expires_at is nil for another user" do      %{conn: conn, user: user} = oauth_access(["read:statuses"]) +    expires_at = DateTime.add(DateTime.utc_now(), 1_000_000)      {:ok, activity} = CommonAPI.post(user, %{status: "foobar", expires_in: 1_000_000}) -    expires_at = -      activity.id -      |> ActivityExpiration.get_by_activity_id() -      |> Map.get(:scheduled_at) -      |> NaiveDateTime.to_iso8601() - -    assert %{"pleroma" => %{"expires_at" => ^expires_at}} = +    assert %{"pleroma" => %{"expires_at" => a_expires_at}} =               conn               |> get("/api/v1/statuses/#{activity.id}")               |> json_response_and_validate_schema(:ok) +    {:ok, a_expires_at, 0} = DateTime.from_iso8601(a_expires_at) +    assert DateTime.diff(expires_at, a_expires_at) == 0 +      %{conn: conn} = oauth_access(["read:statuses"])      assert %{"pleroma" => %{"expires_at" => nil}} = diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index 517cabcff..c6e0268fd 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -114,8 +114,16 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do        {:ok, _reply_from_friend} =          CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee}) -      res_conn = get(conn, "/api/v1/timelines/public") -      [%{"id" => ^activity_id}] = json_response_and_validate_schema(res_conn, 200) +      # Still shows replies from yourself +      {:ok, %{id: reply_from_me}} = +        CommonAPI.post(blocker, %{status: "status", in_reply_to_status_id: reply_from_blockee}) + +      response = +        get(conn, "/api/v1/timelines/public") +        |> json_response_and_validate_schema(200) + +      assert length(response) == 2 +      [%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response      end      test "doesn't return replies if follow is posting with users from blocked domain" do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 9f22f9dcf..a5f39b215 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -5,6 +5,7 @@  defmodule Pleroma.Web.MastodonAPI.AccountViewTest do    use Pleroma.DataCase +  alias Pleroma.Config    alias Pleroma.User    alias Pleroma.UserRelationship    alias Pleroma.Web.CommonAPI @@ -68,7 +69,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          sensitive: false,          pleroma: %{            actor_type: "Person", -          discoverable: false +          discoverable: true          },          fields: []        }, @@ -166,7 +167,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          sensitive: false,          pleroma: %{            actor_type: "Service", -          discoverable: false +          discoverable: true          },          fields: []        }, @@ -448,7 +449,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      test "shows unread_count only to the account owner" do        user = insert(:user) -      insert_list(7, :notification, user: user) +      insert_list(7, :notification, user: user, activity: insert(:note_activity))        other_user = insert(:user)        user = User.get_cached_by_ap_id(user.ap_id) @@ -540,8 +541,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      end    end -  test "uses mediaproxy urls when it's enabled" do +  test "uses mediaproxy urls when it's enabled (regardless of media preview proxy state)" do      clear_config([:media_proxy, :enabled], true) +    clear_config([:media_preview_proxy, :enabled])      user =        insert(:user, @@ -550,20 +552,24 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do          emoji: %{"joker_smile" => "https://evil.website/society.png"}        ) -    AccountView.render("show.json", %{user: user, skip_visibility_check: true}) -    |> Enum.all?(fn -      {key, url} when key in [:avatar, :avatar_static, :header, :header_static] -> -        String.starts_with?(url, Pleroma.Web.base_url()) - -      {:emojis, emojis} -> -        Enum.all?(emojis, fn %{url: url, static_url: static_url} -> -          String.starts_with?(url, Pleroma.Web.base_url()) && -            String.starts_with?(static_url, Pleroma.Web.base_url()) -        end) - -      _ -> -        true -    end) -    |> assert() +    with media_preview_enabled <- [false, true] do +      Config.put([:media_preview_proxy, :enabled], media_preview_enabled) + +      AccountView.render("show.json", %{user: user, skip_visibility_check: true}) +      |> Enum.all?(fn +        {key, url} when key in [:avatar, :avatar_static, :header, :header_static] -> +          String.starts_with?(url, Pleroma.Web.base_url()) + +        {:emojis, emojis} -> +          Enum.all?(emojis, fn %{url: url, static_url: static_url} -> +            String.starts_with?(url, Pleroma.Web.base_url()) && +              String.starts_with?(static_url, Pleroma.Web.base_url()) +          end) + +        _ -> +          true +      end) +      |> assert() +    end    end  end diff --git a/test/web/media_proxy/media_proxy_controller_test.exs b/test/web/media_proxy/media_proxy_controller_test.exs index d4db44c63..33e6873f7 100644 --- a/test/web/media_proxy/media_proxy_controller_test.exs +++ b/test/web/media_proxy/media_proxy_controller_test.exs @@ -8,34 +8,34 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do    import Mock    alias Pleroma.Web.MediaProxy -  alias Pleroma.Web.MediaProxy.MediaProxyController    alias Plug.Conn    setup do      on_exit(fn -> Cachex.clear(:banned_urls_cache) end)    end -  test "it returns 404 when MediaProxy disabled", %{conn: conn} do -    clear_config([:media_proxy, :enabled], false) - -    assert %Conn{ -             status: 404, -             resp_body: "Not Found" -           } = get(conn, "/proxy/hhgfh/eeeee") - -    assert %Conn{ -             status: 404, -             resp_body: "Not Found" -           } = get(conn, "/proxy/hhgfh/eeee/fff") -  end - -  describe "" do +  describe "Media Proxy" do      setup do        clear_config([:media_proxy, :enabled], true)        clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") +        [url: MediaProxy.encode_url("https://google.fn/test.png")]      end +    test "it returns 404 when disabled", %{conn: conn} do +      clear_config([:media_proxy, :enabled], false) + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/hhgfh/eeeee") + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/hhgfh/eeee/fff") +    end +      test "it returns 403 for invalid signature", %{conn: conn, url: url} do        Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")        %{path: path} = URI.parse(url) @@ -56,7 +56,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do               } = get(conn, "/proxy/hhgfh/eeee/fff")      end -    test "redirects on valid url when filename is invalidated", %{conn: conn, url: url} do +    test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do        invalid_url = String.replace(url, "test.png", "test-file.png")        response = get(conn, invalid_url)        assert response.status == 302 @@ -80,42 +80,248 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do      end    end -  describe "filename_matches/3" do -    test "preserves the encoded or decoded path" do -      assert MediaProxyController.filename_matches( -               %{"filename" => "/Hello world.jpg"}, -               "/Hello world.jpg", -               "http://pleroma.social/Hello world.jpg" -             ) == :ok - -      assert MediaProxyController.filename_matches( -               %{"filename" => "/Hello%20world.jpg"}, -               "/Hello%20world.jpg", -               "http://pleroma.social/Hello%20world.jpg" -             ) == :ok - -      assert MediaProxyController.filename_matches( -               %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg"}, -               "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", -               "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg" -             ) == :ok - -      assert MediaProxyController.filename_matches( -               %{"filename" => "/my%2Flong%2Furl%2F2019%2F07%2FS.jp"}, -               "/my%2Flong%2Furl%2F2019%2F07%2FS.jp", -               "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg" -             ) == {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"} -    end - -    test "encoded url are tried to match for proxy as `conn.request_path` encodes the url" do -      # conn.request_path will return encoded url -      request_path = "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg" - -      assert MediaProxyController.filename_matches( -               true, -               request_path, -               "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg" -             ) == :ok +  describe "Media Preview Proxy" do +    setup do +      clear_config([:media_proxy, :enabled], true) +      clear_config([:media_preview_proxy, :enabled], true) +      clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") + +      original_url = "https://google.fn/test.png" + +      [ +        url: MediaProxy.encode_preview_url(original_url), +        media_proxy_url: MediaProxy.encode_url(original_url) +      ] +    end + +    test "returns 404 when media proxy is disabled", %{conn: conn} do +      clear_config([:media_proxy, :enabled], false) + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/eeeee") + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/fff") +    end + +    test "returns 404 when disabled", %{conn: conn} do +      clear_config([:media_preview_proxy, :enabled], false) + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/eeeee") + +      assert %Conn{ +               status: 404, +               resp_body: "Not Found" +             } = get(conn, "/proxy/preview/hhgfh/fff") +    end + +    test "it returns 403 for invalid signature", %{conn: conn, url: url} do +      Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000") +      %{path: path} = URI.parse(url) + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, path) + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, "/proxy/preview/hhgfh/eeee") + +      assert %Conn{ +               status: 403, +               resp_body: "Forbidden" +             } = get(conn, "/proxy/preview/hhgfh/eeee/fff") +    end + +    test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do +      invalid_url = String.replace(url, "test.png", "test-file.png") +      response = get(conn, invalid_url) +      assert response.status == 302 +      assert redirected_to(response) == url +    end + +    test "responds with 424 Failed Dependency if HEAD request to media proxy fails", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 500, body: ""} +      end) + +      response = get(conn, url) +      assert response.status == 424 +      assert response.resp_body == "Can't fetch HTTP headers (HTTP 500)." +    end + +    test "redirects to media proxy URI on unsupported content type", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "application/pdf"}]} +      end) + +      response = get(conn, url) +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url +    end + +    test "with `static=true` and GIF image preview requested, responds with JPEG image", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      # Setting a high :min_content_length to ensure this scenario is not affected by its logic +      clear_config([:media_preview_proxy, :min_content_length], 1_000_000_000) + +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{ +            status: 200, +            body: "", +            headers: [{"content-type", "image/gif"}, {"content-length", "1001718"}] +          } + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.gif")} +      end) + +      response = get(conn, url <> "?static=true") + +      assert response.status == 200 +      assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"] +      assert response.resp_body != "" +    end + +    test "with GIF image preview requested and no `static` param, redirects to media proxy URI", +         %{ +           conn: conn, +           url: url, +           media_proxy_url: media_proxy_url +         } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/gif"}]} +      end) + +      response = get(conn, url) + +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url +    end + +    test "with `static` param and non-GIF image preview requested, " <> +           "redirects to media preview proxy URI without `static` param", +         %{ +           conn: conn, +           url: url, +           media_proxy_url: media_proxy_url +         } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} +      end) + +      response = get(conn, url <> "?static=true") + +      assert response.status == 302 +      assert redirected_to(response) == url +    end + +    test "with :min_content_length setting not matched by Content-Length header, " <> +           "redirects to media proxy URI", +         %{ +           conn: conn, +           url: url, +           media_proxy_url: media_proxy_url +         } do +      clear_config([:media_preview_proxy, :min_content_length], 100_000) + +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{ +            status: 200, +            body: "", +            headers: [{"content-type", "image/gif"}, {"content-length", "5000"}] +          } +      end) + +      response = get(conn, url) + +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url +    end + +    test "thumbnails PNG images into PNG", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/png"}]} + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.png")} +      end) + +      response = get(conn, url) + +      assert response.status == 200 +      assert Conn.get_resp_header(response, "content-type") == ["image/png"] +      assert response.resp_body != "" +    end + +    test "thumbnails JPEG images into JPEG", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")} +      end) + +      response = get(conn, url) + +      assert response.status == 200 +      assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"] +      assert response.resp_body != "" +    end + +    test "redirects to media proxy URI in case of thumbnailing error", %{ +      conn: conn, +      url: url, +      media_proxy_url: media_proxy_url +    } do +      Tesla.Mock.mock(fn +        %{method: "head", url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]} + +        %{method: :get, url: ^media_proxy_url} -> +          %Tesla.Env{status: 200, body: "<html><body>error</body></html>"} +      end) + +      response = get(conn, url) + +      assert response.status == 302 +      assert redirected_to(response) == media_proxy_url      end    end  end diff --git a/test/web/media_proxy/media_proxy_test.exs b/test/web/media_proxy/media_proxy_test.exs index 72885cfdd..0e6df826c 100644 --- a/test/web/media_proxy/media_proxy_test.exs +++ b/test/web/media_proxy/media_proxy_test.exs @@ -6,9 +6,16 @@ defmodule Pleroma.Web.MediaProxyTest do    use ExUnit.Case    use Pleroma.Tests.Helpers +  alias Pleroma.Config    alias Pleroma.Web.Endpoint    alias Pleroma.Web.MediaProxy +  defp decode_result(encoded) do +    [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/") +    {:ok, decoded} = MediaProxy.decode_url(sig, base64) +    decoded +  end +    describe "when enabled" do      setup do: clear_config([:media_proxy, :enabled], true) @@ -35,7 +42,7 @@ defmodule Pleroma.Web.MediaProxyTest do        assert String.starts_with?(                 encoded, -               Pleroma.Config.get([:media_proxy, :base_url], Pleroma.Web.base_url()) +               Config.get([:media_proxy, :base_url], Pleroma.Web.base_url())               )        assert String.ends_with?(encoded, "/logo.png") @@ -75,6 +82,64 @@ defmodule Pleroma.Web.MediaProxyTest do        assert MediaProxy.decode_url(sig, base64) == {:error, :invalid_signature}      end +    def test_verify_request_path_and_url(request_path, url, expected_result) do +      assert MediaProxy.verify_request_path_and_url(request_path, url) == expected_result + +      assert MediaProxy.verify_request_path_and_url( +               %Plug.Conn{ +                 params: %{"filename" => Path.basename(request_path)}, +                 request_path: request_path +               }, +               url +             ) == expected_result +    end + +    test "if first arg of `verify_request_path_and_url/2` is a Plug.Conn without \"filename\" " <> +           "parameter, `verify_request_path_and_url/2` returns :ok " do +      assert MediaProxy.verify_request_path_and_url( +               %Plug.Conn{params: %{}, request_path: "/some/path"}, +               "https://instance.com/file.jpg" +             ) == :ok + +      assert MediaProxy.verify_request_path_and_url( +               %Plug.Conn{params: %{}, request_path: "/path/to/file.jpg"}, +               "https://instance.com/file.jpg" +             ) == :ok +    end + +    test "`verify_request_path_and_url/2` preserves the encoded or decoded path" do +      test_verify_request_path_and_url( +        "/Hello world.jpg", +        "http://pleroma.social/Hello world.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        "/Hello%20world.jpg", +        "http://pleroma.social/Hello%20world.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        "/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", +        "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        # Note: `conn.request_path` returns encoded url +        "/ANALYSE-DAI-_-LE-STABLECOIN-100-D%C3%89CENTRALIS%C3%89-BQ.jpg", +        "https://mydomain.com/uploads/2019/07/ANALYSE-DAI-_-LE-STABLECOIN-100-DÉCENTRALISÉ-BQ.jpg", +        :ok +      ) + +      test_verify_request_path_and_url( +        "/my%2Flong%2Furl%2F2019%2F07%2FS", +        "http://pleroma.social/my%2Flong%2Furl%2F2019%2F07%2FS.jpg", +        {:wrong_filename, "my%2Flong%2Furl%2F2019%2F07%2FS.jpg"} +      ) +    end +      test "uses the configured base_url" do        base_url = "https://cache.pleroma.social"        clear_config([:media_proxy, :base_url], base_url) @@ -124,12 +189,6 @@ defmodule Pleroma.Web.MediaProxyTest do      end    end -  defp decode_result(encoded) do -    [_, "proxy", sig, base64 | _] = URI.parse(encoded).path |> String.split("/") -    {:ok, decoded} = MediaProxy.decode_url(sig, base64) -    decoded -  end -    describe "whitelist" do      setup do: clear_config([:media_proxy, :enabled], true) diff --git a/test/web/metadata/metadata_test.exs b/test/web/metadata/metadata_test.exs index 9d3121b7b..ca6cbe67f 100644 --- a/test/web/metadata/metadata_test.exs +++ b/test/web/metadata/metadata_test.exs @@ -16,7 +16,14 @@ defmodule Pleroma.Web.MetadataTest do      end      test "for local user" do -      user = insert(:user) +      user = insert(:user, discoverable: false) + +      assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~ +               "<meta content=\"noindex, noarchive\" name=\"robots\">" +    end + +    test "for local user set to discoverable" do +      user = insert(:user, discoverable: true)        refute Pleroma.Web.Metadata.build_tags(%{user: user}) =~                 "<meta content=\"noindex, noarchive\" name=\"robots\">" @@ -24,11 +31,19 @@ defmodule Pleroma.Web.MetadataTest do    end    describe "no metadata for private instances" do -    test "for local user" do +    test "for local user set to discoverable" do        clear_config([:instance, :public], false) -      user = insert(:user, bio: "This is my secret fedi account bio") +      user = insert(:user, bio: "This is my secret fedi account bio", discoverable: true)        assert "" = Pleroma.Web.Metadata.build_tags(%{user: user})      end + +    test "search exclusion metadata is included" do +      clear_config([:instance, :public], false) +      user = insert(:user, bio: "This is my secret fedi account bio", discoverable: false) + +      assert ~s(<meta content="noindex, noarchive" name="robots">) == +               Pleroma.Web.Metadata.build_tags(%{user: user}) +    end    end  end diff --git a/test/web/metadata/restrict_indexing_test.exs b/test/web/metadata/restrict_indexing_test.exs index aad0bac42..6b3a65372 100644 --- a/test/web/metadata/restrict_indexing_test.exs +++ b/test/web/metadata/restrict_indexing_test.exs @@ -14,8 +14,14 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexingTest do      test "for local user" do        assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ -               user: %Pleroma.User{local: true} +               user: %Pleroma.User{local: true, discoverable: true}               }) == []      end + +    test "for local user when discoverable is false" do +      assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{ +               user: %Pleroma.User{local: true, discoverable: false} +             }) == [{:meta, [name: "robots", content: "noindex, noarchive"], []}] +    end    end  end diff --git a/test/web/oauth/token_test.exs b/test/web/oauth/token_test.exs index 40d71eb59..c88b9cc98 100644 --- a/test/web/oauth/token_test.exs +++ b/test/web/oauth/token_test.exs @@ -69,17 +69,4 @@ defmodule Pleroma.Web.OAuth.TokenTest do      assert tokens == 2    end - -  test "deletes expired tokens" do -    insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3)) -    insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3)) -    t3 = insert(:oauth_token) -    t4 = insert(:oauth_token, valid_until: Timex.shift(Timex.now(), minutes: 10)) -    {tokens, _} = Token.delete_expired_tokens() -    assert tokens == 2 -    available_tokens = Pleroma.Repo.all(Token) - -    token_ids = available_tokens |> Enum.map(& &1.id) -    assert token_ids == [t3.id, t4.id] -  end  end diff --git a/test/web/pleroma_api/controllers/chat_controller_test.exs b/test/web/pleroma_api/controllers/chat_controller_test.exs index 40f7c72ca..11d5ba373 100644 --- a/test/web/pleroma_api/controllers/chat_controller_test.exs +++ b/test/web/pleroma_api/controllers/chat_controller_test.exs @@ -100,7 +100,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do          |> post("/api/v1/pleroma/chats/#{chat.id}/messages")          |> json_response_and_validate_schema(400) -      assert result +      assert %{"error" => "no_content"} == result      end      test "it works with an attachment", %{conn: conn, user: user} do @@ -126,6 +126,23 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do        assert result["attachment"]      end + +    test "gets MRF reason when rejected", %{conn: conn, user: user} do +      clear_config([:mrf_keyword, :reject], ["GNO"]) +      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy]) + +      other_user = insert(:user) + +      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + +      result = +        conn +        |> put_req_header("content-type", "application/json") +        |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "GNO/Linux"}) +        |> json_response_and_validate_schema(422) + +      assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} == result +    end    end    describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do diff --git a/test/web/pleroma_api/controllers/user_import_controller_test.exs b/test/web/pleroma_api/controllers/user_import_controller_test.exs new file mode 100644 index 000000000..433c97e81 --- /dev/null +++ b/test/web/pleroma_api/controllers/user_import_controller_test.exs @@ -0,0 +1,235 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do +  use Pleroma.Web.ConnCase +  use Oban.Testing, repo: Pleroma.Repo + +  alias Pleroma.Config +  alias Pleroma.Tests.ObanHelpers + +  import Pleroma.Factory +  import Mock + +  setup do +    Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  describe "POST /api/pleroma/follow_import" do +    setup do: oauth_access(["follow"]) + +    test "it returns HTTP 200", %{conn: conn} do +      user2 = insert(:user) + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"}) +               |> json_response_and_validate_schema(200) +    end + +    test "it imports follow lists from file", %{conn: conn} do +      user2 = insert(:user) + +      with_mocks([ +        {File, [], +         read!: fn "follow_list.txt" -> +           "Account address,Show boosts\n#{user2.ap_id},true" +         end} +      ]) do +        assert "job started" == +                 conn +                 |> put_req_header("content-type", "application/json") +                 |> post("/api/pleroma/follow_import", %{ +                   "list" => %Plug.Upload{path: "follow_list.txt"} +                 }) +                 |> json_response_and_validate_schema(200) + +        assert [{:ok, job_result}] = ObanHelpers.perform_all() +        assert job_result == [user2] +      end +    end + +    test "it imports new-style mastodon follow lists", %{conn: conn} do +      user2 = insert(:user) + +      response = +        conn +        |> put_req_header("content-type", "application/json") +        |> post("/api/pleroma/follow_import", %{ +          "list" => "Account address,Show boosts\n#{user2.ap_id},true" +        }) +        |> json_response_and_validate_schema(200) + +      assert response == "job started" +    end + +    test "requires 'follow' or 'write:follows' permissions" do +      token1 = insert(:oauth_token, scopes: ["read", "write"]) +      token2 = insert(:oauth_token, scopes: ["follow"]) +      token3 = insert(:oauth_token, scopes: ["something"]) +      another_user = insert(:user) + +      for token <- [token1, token2, token3] do +        conn = +          build_conn() +          |> put_req_header("authorization", "Bearer #{token.token}") +          |> put_req_header("content-type", "application/json") +          |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) + +        if token == token3 do +          assert %{"error" => "Insufficient permissions: follow | write:follows."} == +                   json_response(conn, 403) +        else +          assert json_response(conn, 200) +        end +      end +    end + +    test "it imports follows with different nickname variations", %{conn: conn} do +      users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "  ", +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join("\n") + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/follow_import", %{"list" => identifiers}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == users +    end +  end + +  describe "POST /api/pleroma/blocks_import" do +    # Note: "follow" or "write:blocks" permission is required +    setup do: oauth_access(["write:blocks"]) + +    test "it returns HTTP 200", %{conn: conn} do +      user2 = insert(:user) + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"}) +               |> json_response_and_validate_schema(200) +    end + +    test "it imports blocks users from file", %{conn: conn} do +      users = [user2, user3] = insert_list(2, :user) + +      with_mocks([ +        {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} +      ]) do +        assert "job started" == +                 conn +                 |> put_req_header("content-type", "application/json") +                 |> post("/api/pleroma/blocks_import", %{ +                   "list" => %Plug.Upload{path: "blocks_list.txt"} +                 }) +                 |> json_response_and_validate_schema(200) + +        assert [{:ok, job_result}] = ObanHelpers.perform_all() +        assert job_result == users +      end +    end + +    test "it imports blocks with different nickname variations", %{conn: conn} do +      users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join(" ") + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == users +    end +  end + +  describe "POST /api/pleroma/mutes_import" do +    # Note: "follow" or "write:mutes" permission is required +    setup do: oauth_access(["write:mutes"]) + +    test "it returns HTTP 200", %{user: user, conn: conn} do +      user2 = insert(:user) + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/mutes_import", %{"list" => "#{user2.ap_id}"}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == [user2] +      assert Pleroma.User.mutes?(user, user2) +    end + +    test "it imports mutes users from file", %{user: user, conn: conn} do +      users = [user2, user3] = insert_list(2, :user) + +      with_mocks([ +        {File, [], read!: fn "mutes_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} +      ]) do +        assert "job started" == +                 conn +                 |> put_req_header("content-type", "application/json") +                 |> post("/api/pleroma/mutes_import", %{ +                   "list" => %Plug.Upload{path: "mutes_list.txt"} +                 }) +                 |> json_response_and_validate_schema(200) + +        assert [{:ok, job_result}] = ObanHelpers.perform_all() +        assert job_result == users +        assert Enum.all?(users, &Pleroma.User.mutes?(user, &1)) +      end +    end + +    test "it imports mutes with different nickname variations", %{user: user, conn: conn} do +      users = [user2, user3, user4, user5, user6] = insert_list(5, :user) + +      identifiers = +        [ +          user2.ap_id, +          user3.nickname, +          "@" <> user4.nickname, +          user5.nickname <> "@localhost", +          "@" <> user6.nickname <> "@localhost" +        ] +        |> Enum.join(" ") + +      assert "job started" == +               conn +               |> put_req_header("content-type", "application/json") +               |> post("/api/pleroma/mutes_import", %{"list" => identifiers}) +               |> json_response_and_validate_schema(200) + +      assert [{:ok, job_result}] = ObanHelpers.perform_all() +      assert job_result == users +      assert Enum.all?(users, &Pleroma.User.mutes?(user, &1)) +    end +  end +end diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index aeb5c1fbd..c7c17e156 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -12,7 +12,9 @@ defmodule Pleroma.Web.Push.ImplTest do    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.Push.Impl    alias Pleroma.Web.Push.Subscription +  alias Pleroma.Web.WebPushHttpClientMock +  import Mock    import Pleroma.Factory    setup do @@ -78,6 +80,22 @@ defmodule Pleroma.Web.Push.ImplTest do      assert Impl.push_message(@message, @sub, @api_key, %Subscription{}) == :ok    end +  test_with_mock "uses WebPushHttpClientMock as an HTTP client", WebPushHttpClientMock, +    post: fn _, _, _ -> {:ok, %{status_code: 200}} end do +    Impl.push_message(@message, @sub, @api_key, %Subscription{}) +    assert_called(WebPushHttpClientMock.post("https://example.com/example/1234", :_, :_)) +  end + +  test_with_mock "uses Pleroma.HTTP as an HTTP client", Pleroma.HTTP, +    post: fn _, _, _ -> {:ok, %{status_code: 200}} end do +    client = Application.get_env(:web_push_encryption, :http_client) +    on_exit(fn -> Application.put_env(:web_push_encryption, :http_client, client) end) +    Application.put_env(:web_push_encryption, :http_client, Pleroma.HTTP) + +    Impl.push_message(@message, @sub, @api_key, %Subscription{}) +    assert_called(Pleroma.HTTP.post("https://example.com/example/1234", :_, :_)) +  end +    @tag capture_log: true    test "fail message sending" do      assert Impl.push_message( diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs index 21ae35f8b..6d00c2af5 100644 --- a/test/web/rich_media/parser_test.exs +++ b/test/web/rich_media/parser_test.exs @@ -56,6 +56,27 @@ defmodule Pleroma.Web.RichMedia.ParserTest do        %{method: :get, url: "http://example.com/error"} ->          {:error, :overload} + +      %{ +        method: :head, +        url: "http://example.com/huge-page" +      } -> +        %Tesla.Env{ +          status: 200, +          headers: [{"content-length", "2000001"}, {"content-type", "text/html"}] +        } + +      %{ +        method: :head, +        url: "http://example.com/pdf-file" +      } -> +        %Tesla.Env{ +          status: 200, +          headers: [{"content-length", "1000000"}, {"content-type", "application/pdf"}] +        } + +      %{method: :head} -> +        %Tesla.Env{status: 404, body: "", headers: []}      end)      :ok @@ -144,4 +165,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do    test "returns error if getting page was not successful" do      assert {:error, :overload} = Parser.parse("http://example.com/error")    end + +  test "does a HEAD request to check if the body is too large" do +    assert {:error, :body_too_large} = Parser.parse("http://example.com/huge-page") +  end + +  test "does a HEAD request to check if the body is html" do +    assert {:error, {:content_type, _}} = Parser.parse("http://example.com/pdf-file") +  end  end diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index d56d74464..185724a9f 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -21,92 +21,148 @@ defmodule Pleroma.Web.StreamerTest do    setup do: clear_config([:instance, :skip_thread_containment]) -  describe "get_topic without an user" do +  describe "get_topic/_ (unauthenticated)" do      test "allows public" do -      assert {:ok, "public"} = Streamer.get_topic("public", nil) -      assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil) -      assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil) -      assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil) +      assert {:ok, "public"} = Streamer.get_topic("public", nil, nil) +      assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil, nil) +      assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil, nil) +      assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil, nil)      end      test "allows hashtag streams" do -      assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, %{"tag" => "cofe"}) +      assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, nil, %{"tag" => "cofe"})      end      test "disallows user streams" do -      assert {:error, _} = Streamer.get_topic("user", nil) -      assert {:error, _} = Streamer.get_topic("user:notification", nil) -      assert {:error, _} = Streamer.get_topic("direct", nil) +      assert {:error, _} = Streamer.get_topic("user", nil, nil) +      assert {:error, _} = Streamer.get_topic("user:notification", nil, nil) +      assert {:error, _} = Streamer.get_topic("direct", nil, nil)      end      test "disallows list streams" do -      assert {:error, _} = Streamer.get_topic("list", nil, %{"list" => 42}) +      assert {:error, _} = Streamer.get_topic("list", nil, nil, %{"list" => 42})      end    end -  describe "get_topic with an user" do -    setup do -      user = insert(:user) -      {:ok, %{user: user}} -    end +  describe "get_topic/_ (authenticated)" do +    setup do: oauth_access(["read"]) + +    test "allows public streams (regardless of OAuth token scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      with oauth_token <- [nil, read_oauth_token] do +        assert {:ok, "public"} = Streamer.get_topic("public", user, oauth_token) +        assert {:ok, "public:local"} = Streamer.get_topic("public:local", user, oauth_token) +        assert {:ok, "public:media"} = Streamer.get_topic("public:media", user, oauth_token) -    test "allows public streams", %{user: user} do -      assert {:ok, "public"} = Streamer.get_topic("public", user) -      assert {:ok, "public:local"} = Streamer.get_topic("public:local", user) -      assert {:ok, "public:media"} = Streamer.get_topic("public:media", user) -      assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", user) +        assert {:ok, "public:local:media"} = +                 Streamer.get_topic("public:local:media", user, oauth_token) +      end      end -    test "allows user streams", %{user: user} do +    test "allows user streams (with proper OAuth token scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      %{token: read_notifications_token} = oauth_access(["read:notifications"], user: user) +      %{token: read_statuses_token} = oauth_access(["read:statuses"], user: user) +      %{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user) +        expected_user_topic = "user:#{user.id}" -      expected_notif_topic = "user:notification:#{user.id}" +      expected_notification_topic = "user:notification:#{user.id}"        expected_direct_topic = "direct:#{user.id}" -      assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user) -      assert {:ok, ^expected_notif_topic} = Streamer.get_topic("user:notification", user) -      assert {:ok, ^expected_direct_topic} = Streamer.get_topic("direct", user) +      expected_pleroma_chat_topic = "user:pleroma_chat:#{user.id}" + +      for valid_user_token <- [read_oauth_token, read_statuses_token] do +        assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user, valid_user_token) + +        assert {:ok, ^expected_direct_topic} = +                 Streamer.get_topic("direct", user, valid_user_token) + +        assert {:ok, ^expected_pleroma_chat_topic} = +                 Streamer.get_topic("user:pleroma_chat", user, valid_user_token) +      end + +      for invalid_user_token <- [read_notifications_token, badly_scoped_token], +          user_topic <- ["user", "direct", "user:pleroma_chat"] do +        assert {:error, :unauthorized} = Streamer.get_topic(user_topic, user, invalid_user_token) +      end + +      for valid_notification_token <- [read_oauth_token, read_notifications_token] do +        assert {:ok, ^expected_notification_topic} = +                 Streamer.get_topic("user:notification", user, valid_notification_token) +      end + +      for invalid_notification_token <- [read_statuses_token, badly_scoped_token] do +        assert {:error, :unauthorized} = +                 Streamer.get_topic("user:notification", user, invalid_notification_token) +      end      end -    test "allows hashtag streams", %{user: user} do -      assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", user, %{"tag" => "cofe"}) +    test "allows hashtag streams (regardless of OAuth token scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      for oauth_token <- [nil, read_oauth_token] do +        assert {:ok, "hashtag:cofe"} = +                 Streamer.get_topic("hashtag", user, oauth_token, %{"tag" => "cofe"}) +      end      end -    test "disallows registering to an user stream", %{user: user} do +    test "disallows registering to another user's stream", %{user: user, token: read_oauth_token} do        another_user = insert(:user) -      assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user) -      assert {:error, _} = Streamer.get_topic("user:notification:#{another_user.id}", user) -      assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user) +      assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user, read_oauth_token) + +      assert {:error, _} = +               Streamer.get_topic("user:notification:#{another_user.id}", user, read_oauth_token) + +      assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user, read_oauth_token)      end -    test "allows list stream that are owned by the user", %{user: user} do +    test "allows list stream that are owned by the user (with `read` or `read:lists` scopes)", %{ +      user: user, +      token: read_oauth_token +    } do +      %{token: read_lists_token} = oauth_access(["read:lists"], user: user) +      %{token: invalid_token} = oauth_access(["irrelevant:scope"], user: user)        {:ok, list} = List.create("Test", user) -      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user) -      assert {:ok, _} = Streamer.get_topic("list", user, %{"list" => list.id}) + +      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user, read_oauth_token) + +      for valid_token <- [read_oauth_token, read_lists_token] do +        assert {:ok, _} = Streamer.get_topic("list", user, valid_token, %{"list" => list.id}) +      end + +      assert {:error, _} = Streamer.get_topic("list", user, invalid_token, %{"list" => list.id})      end -    test "disallows list stream that are not owned by the user", %{user: user} do +    test "disallows list stream that are not owned by the user", %{user: user, token: oauth_token} do        another_user = insert(:user)        {:ok, list} = List.create("Test", another_user) -      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user) -      assert {:error, _} = Streamer.get_topic("list", user, %{"list" => list.id}) + +      assert {:error, _} = Streamer.get_topic("list:#{list.id}", user, oauth_token) +      assert {:error, _} = Streamer.get_topic("list", user, oauth_token, %{"list" => list.id})      end    end    describe "user streams" do      setup do -      user = insert(:user) +      %{user: user, token: token} = oauth_access(["read"])        notify = insert(:notification, user: user, activity: build(:note_activity)) -      {:ok, %{user: user, notify: notify}} +      {:ok, %{user: user, notify: notify, token: token}}      end -    test "it streams the user's post in the 'user' stream", %{user: user} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it streams the user's post in the 'user' stream", %{user: user, token: oauth_token} do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) +        assert_receive {:render_with_user, _, _, ^activity}        refute Streamer.filtered_by_user?(user, activity)      end -    test "it streams boosts of the user in the 'user' stream", %{user: user} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it streams boosts of the user in the 'user' stream", %{user: user, token: oauth_token} do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) @@ -117,9 +173,10 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it does not stream announces of the user's own posts in the 'user' stream", %{ -      user: user +      user: user, +      token: oauth_token      } do -      Streamer.get_topic_and_add_socket("user", user) +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) @@ -129,9 +186,10 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it does stream notifications announces of the user's own posts in the 'user' stream", %{ -      user: user +      user: user, +      token: oauth_token      } do -      Streamer.get_topic_and_add_socket("user", user) +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) @@ -145,8 +203,11 @@ defmodule Pleroma.Web.StreamerTest do        refute Streamer.filtered_by_user?(user, notification)      end -    test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it streams boosts of mastodon user in the 'user' stream", %{ +      user: user, +      token: oauth_token +    } do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        other_user = insert(:user)        {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) @@ -164,21 +225,34 @@ defmodule Pleroma.Web.StreamerTest do        refute Streamer.filtered_by_user?(user, announce)      end -    test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do -      Streamer.get_topic_and_add_socket("user", user) +    test "it sends notify to in the 'user' stream", %{ +      user: user, +      token: oauth_token, +      notify: notify +    } do +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        Streamer.stream("user", notify) +        assert_receive {:render_with_user, _, _, ^notify}        refute Streamer.filtered_by_user?(user, notify)      end -    test "it sends notify to in the 'user:notification' stream", %{user: user, notify: notify} do -      Streamer.get_topic_and_add_socket("user:notification", user) +    test "it sends notify to in the 'user:notification' stream", %{ +      user: user, +      token: oauth_token, +      notify: notify +    } do +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        Streamer.stream("user:notification", notify) +        assert_receive {:render_with_user, _, _, ^notify}        refute Streamer.filtered_by_user?(user, notify)      end -    test "it sends chat messages to the 'user:pleroma_chat' stream", %{user: user} do +    test "it sends chat messages to the 'user:pleroma_chat' stream", %{ +      user: user, +      token: oauth_token +    } do        other_user = insert(:user)        {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") @@ -187,7 +261,7 @@ defmodule Pleroma.Web.StreamerTest do        cm_ref = MessageReference.for_chat_and_object(chat, object)        cm_ref = %{cm_ref | chat: chat, object: object} -      Streamer.get_topic_and_add_socket("user:pleroma_chat", user) +      Streamer.get_topic_and_add_socket("user:pleroma_chat", user, oauth_token)        Streamer.stream("user:pleroma_chat", {user, cm_ref})        text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) @@ -196,7 +270,7 @@ defmodule Pleroma.Web.StreamerTest do        assert_receive {:text, ^text}      end -    test "it sends chat messages to the 'user' stream", %{user: user} do +    test "it sends chat messages to the 'user' stream", %{user: user, token: oauth_token} do        other_user = insert(:user)        {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") @@ -205,7 +279,7 @@ defmodule Pleroma.Web.StreamerTest do        cm_ref = MessageReference.for_chat_and_object(chat, object)        cm_ref = %{cm_ref | chat: chat, object: object} -      Streamer.get_topic_and_add_socket("user", user) +      Streamer.get_topic_and_add_socket("user", user, oauth_token)        Streamer.stream("user", {user, cm_ref})        text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) @@ -214,7 +288,10 @@ defmodule Pleroma.Web.StreamerTest do        assert_receive {:text, ^text}      end -    test "it sends chat message notifications to the 'user:notification' stream", %{user: user} do +    test "it sends chat message notifications to the 'user:notification' stream", %{ +      user: user, +      token: oauth_token +    } do        other_user = insert(:user)        {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey") @@ -223,19 +300,21 @@ defmodule Pleroma.Web.StreamerTest do          Repo.get_by(Pleroma.Notification, user_id: user.id, activity_id: create_activity.id)          |> Repo.preload(:activity) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        Streamer.stream("user:notification", notify) +        assert_receive {:render_with_user, _, _, ^notify}        refute Streamer.filtered_by_user?(user, notify)      end      test "it doesn't send notify to the 'user:notification' stream when a user is blocked", %{ -      user: user +      user: user, +      token: oauth_token      } do        blocked = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, activity} = CommonAPI.post(user, %{status: ":("})        {:ok, _} = CommonAPI.favorite(blocked, activity.id) @@ -244,14 +323,15 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it doesn't send notify to the 'user:notification' stream when a thread is muted", %{ -      user: user +      user: user, +      token: oauth_token      } do        user2 = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"})        {:ok, _} = CommonAPI.add_mute(user, activity) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id) @@ -260,12 +340,13 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it sends favorite to 'user:notification' stream'", %{ -      user: user +      user: user, +      token: oauth_token      } do        user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})        {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)        assert_receive {:render_with_user, _, "notification.json", notif} @@ -274,13 +355,14 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it doesn't send the 'user:notification' stream' when a domain is blocked", %{ -      user: user +      user: user, +      token: oauth_token      } do        user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})        {:ok, user} = User.block_domain(user, "hecking-lewd-place.com")        {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, favorite_activity} = CommonAPI.favorite(user2, activity.id)        refute_receive _ @@ -288,7 +370,8 @@ defmodule Pleroma.Web.StreamerTest do      end      test "it sends follow activities to the 'user:notification' stream", %{ -      user: user +      user: user, +      token: oauth_token      } do        user_url = user.ap_id        user2 = insert(:user) @@ -303,7 +386,7 @@ defmodule Pleroma.Web.StreamerTest do            %Tesla.Env{status: 200, body: body}        end) -      Streamer.get_topic_and_add_socket("user:notification", user) +      Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)        {:ok, _follower, _followed, follow_activity} = CommonAPI.follow(user2, user)        assert_receive {:render_with_user, _, "notification.json", notif} @@ -312,51 +395,53 @@ defmodule Pleroma.Web.StreamerTest do      end    end -  test "it sends to public authenticated" do -    user = insert(:user) -    other_user = insert(:user) +  describe "public streams" do +    test "it sends to public (authenticated)" do +      %{user: user, token: oauth_token} = oauth_access(["read"]) +      other_user = insert(:user) -    Streamer.get_topic_and_add_socket("public", other_user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token) -    {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) -    assert_receive {:render_with_user, _, _, ^activity} -    refute Streamer.filtered_by_user?(user, activity) -  end +      {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) +      assert_receive {:render_with_user, _, _, ^activity} +      refute Streamer.filtered_by_user?(other_user, activity) +    end -  test "works for deletions" do -    user = insert(:user) -    other_user = insert(:user) -    {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) +    test "it sends to public (unauthenticated)" do +      user = insert(:user) -    Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", nil, nil) -    {:ok, _} = CommonAPI.delete(activity.id, other_user) -    activity_id = activity.id -    assert_receive {:text, event} -    assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) -  end +      {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) +      activity_id = activity.id +      assert_receive {:text, event} +      assert %{"event" => "update", "payload" => payload} = Jason.decode!(event) +      assert %{"id" => ^activity_id} = Jason.decode!(payload) -  test "it sends to public unauthenticated" do -    user = insert(:user) +      {:ok, _} = CommonAPI.delete(activity.id, user) +      assert_receive {:text, event} +      assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) +    end -    Streamer.get_topic_and_add_socket("public", nil) +    test "handles deletions" do +      %{user: user, token: oauth_token} = oauth_access(["read"]) +      other_user = insert(:user) +      {:ok, activity} = CommonAPI.post(other_user, %{status: "Test"}) -    {:ok, activity} = CommonAPI.post(user, %{status: "Test"}) -    activity_id = activity.id -    assert_receive {:text, event} -    assert %{"event" => "update", "payload" => payload} = Jason.decode!(event) -    assert %{"id" => ^activity_id} = Jason.decode!(payload) +      Streamer.get_topic_and_add_socket("public", user, oauth_token) -    {:ok, _} = CommonAPI.delete(activity.id, user) -    assert_receive {:text, event} -    assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) +      {:ok, _} = CommonAPI.delete(activity.id, other_user) +      activity_id = activity.id +      assert_receive {:text, event} +      assert %{"event" => "delete", "payload" => ^activity_id} = Jason.decode!(event) +    end    end -  describe "thread_containment" do +  describe "thread_containment/2" do      test "it filters to user if recipients invalid and thread containment is enabled" do        Pleroma.Config.put([:instance, :skip_thread_containment], false)        author = insert(:user) -      user = insert(:user) +      %{user: user, token: oauth_token} = oauth_access(["read"])        User.follow(user, author, :follow_accept)        activity = @@ -368,7 +453,7 @@ defmodule Pleroma.Web.StreamerTest do              )          ) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        Streamer.stream("public", activity)        assert_receive {:render_with_user, _, _, ^activity}        assert Streamer.filtered_by_user?(user, activity) @@ -377,7 +462,7 @@ defmodule Pleroma.Web.StreamerTest do      test "it sends message if recipients invalid and thread containment is disabled" do        Pleroma.Config.put([:instance, :skip_thread_containment], true)        author = insert(:user) -      user = insert(:user) +      %{user: user, token: oauth_token} = oauth_access(["read"])        User.follow(user, author, :follow_accept)        activity = @@ -389,7 +474,7 @@ defmodule Pleroma.Web.StreamerTest do              )          ) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        Streamer.stream("public", activity)        assert_receive {:render_with_user, _, _, ^activity} @@ -400,6 +485,7 @@ defmodule Pleroma.Web.StreamerTest do        Pleroma.Config.put([:instance, :skip_thread_containment], false)        author = insert(:user)        user = insert(:user, skip_thread_containment: true) +      %{token: oauth_token} = oauth_access(["read"], user: user)        User.follow(user, author, :follow_accept)        activity = @@ -411,7 +497,7 @@ defmodule Pleroma.Web.StreamerTest do              )          ) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        Streamer.stream("public", activity)        assert_receive {:render_with_user, _, _, ^activity} @@ -420,23 +506,26 @@ defmodule Pleroma.Web.StreamerTest do    end    describe "blocks" do -    test "it filters messages involving blocked users" do -      user = insert(:user) +    setup do: oauth_access(["read"]) + +    test "it filters messages involving blocked users", %{user: user, token: oauth_token} do        blocked_user = insert(:user)        {:ok, _user_relationship} = User.block(user, blocked_user) -      Streamer.get_topic_and_add_socket("public", user) +      Streamer.get_topic_and_add_socket("public", user, oauth_token)        {:ok, activity} = CommonAPI.post(blocked_user, %{status: "Test"})        assert_receive {:render_with_user, _, _, ^activity}        assert Streamer.filtered_by_user?(user, activity)      end -    test "it filters messages transitively involving blocked users" do -      blocker = insert(:user) +    test "it filters messages transitively involving blocked users", %{ +      user: blocker, +      token: blocker_token +    } do        blockee = insert(:user)        friend = insert(:user) -      Streamer.get_topic_and_add_socket("public", blocker) +      Streamer.get_topic_and_add_socket("public", blocker, blocker_token)        {:ok, _user_relationship} = User.block(blocker, blockee) @@ -458,8 +547,9 @@ defmodule Pleroma.Web.StreamerTest do    end    describe "lists" do -    test "it doesn't send unwanted DMs to list" do -      user_a = insert(:user) +    setup do: oauth_access(["read"]) + +    test "it doesn't send unwanted DMs to list", %{user: user_a, token: user_a_token} do        user_b = insert(:user)        user_c = insert(:user) @@ -468,7 +558,7 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, list} = List.create("Test", user_a)        {:ok, list} = List.follow(list, user_b) -      Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) +      Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id})        {:ok, _activity} =          CommonAPI.post(user_b, %{ @@ -479,14 +569,13 @@ defmodule Pleroma.Web.StreamerTest do        refute_receive _      end -    test "it doesn't send unwanted private posts to list" do -      user_a = insert(:user) +    test "it doesn't send unwanted private posts to list", %{user: user_a, token: user_a_token} do        user_b = insert(:user)        {:ok, list} = List.create("Test", user_a)        {:ok, list} = List.follow(list, user_b) -      Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) +      Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id})        {:ok, _activity} =          CommonAPI.post(user_b, %{ @@ -497,8 +586,7 @@ defmodule Pleroma.Web.StreamerTest do        refute_receive _      end -    test "it sends wanted private posts to list" do -      user_a = insert(:user) +    test "it sends wanted private posts to list", %{user: user_a, token: user_a_token} do        user_b = insert(:user)        {:ok, user_a} = User.follow(user_a, user_b) @@ -506,7 +594,7 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, list} = List.create("Test", user_a)        {:ok, list} = List.follow(list, user_b) -      Streamer.get_topic_and_add_socket("list", user_a, %{"list" => list.id}) +      Streamer.get_topic_and_add_socket("list", user_a, user_a_token, %{"list" => list.id})        {:ok, activity} =          CommonAPI.post(user_b, %{ @@ -520,8 +608,9 @@ defmodule Pleroma.Web.StreamerTest do    end    describe "muted reblogs" do -    test "it filters muted reblogs" do -      user1 = insert(:user) +    setup do: oauth_access(["read"]) + +    test "it filters muted reblogs", %{user: user1, token: user1_token} do        user2 = insert(:user)        user3 = insert(:user)        CommonAPI.follow(user1, user2) @@ -529,34 +618,38 @@ defmodule Pleroma.Web.StreamerTest do        {:ok, create_activity} = CommonAPI.post(user3, %{status: "I'm kawen"}) -      Streamer.get_topic_and_add_socket("user", user1) +      Streamer.get_topic_and_add_socket("user", user1, user1_token)        {:ok, announce_activity} = CommonAPI.repeat(create_activity.id, user2)        assert_receive {:render_with_user, _, _, ^announce_activity}        assert Streamer.filtered_by_user?(user1, announce_activity)      end -    test "it filters reblog notification for reblog-muted actors" do -      user1 = insert(:user) +    test "it filters reblog notification for reblog-muted actors", %{ +      user: user1, +      token: user1_token +    } do        user2 = insert(:user)        CommonAPI.follow(user1, user2)        CommonAPI.hide_reblogs(user1, user2)        {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"}) -      Streamer.get_topic_and_add_socket("user", user1) +      Streamer.get_topic_and_add_socket("user", user1, user1_token)        {:ok, _announce_activity} = CommonAPI.repeat(create_activity.id, user2)        assert_receive {:render_with_user, _, "notification.json", notif}        assert Streamer.filtered_by_user?(user1, notif)      end -    test "it send non-reblog notification for reblog-muted actors" do -      user1 = insert(:user) +    test "it send non-reblog notification for reblog-muted actors", %{ +      user: user1, +      token: user1_token +    } do        user2 = insert(:user)        CommonAPI.follow(user1, user2)        CommonAPI.hide_reblogs(user1, user2)        {:ok, create_activity} = CommonAPI.post(user1, %{status: "I'm kawen"}) -      Streamer.get_topic_and_add_socket("user", user1) +      Streamer.get_topic_and_add_socket("user", user1, user1_token)        {:ok, _favorite_activity} = CommonAPI.favorite(user2, create_activity.id)        assert_receive {:render_with_user, _, "notification.json", notif} @@ -564,27 +657,28 @@ defmodule Pleroma.Web.StreamerTest do      end    end -  test "it filters posts from muted threads" do -    user = insert(:user) -    user2 = insert(:user) -    Streamer.get_topic_and_add_socket("user", user2) -    {:ok, user2, user, _activity} = CommonAPI.follow(user2, user) -    {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) -    {:ok, _} = CommonAPI.add_mute(user2, activity) -    assert_receive {:render_with_user, _, _, ^activity} -    assert Streamer.filtered_by_user?(user2, activity) +  describe "muted threads" do +    test "it filters posts from muted threads" do +      user = insert(:user) +      %{user: user2, token: user2_token} = oauth_access(["read"]) +      Streamer.get_topic_and_add_socket("user", user2, user2_token) + +      {:ok, user2, user, _activity} = CommonAPI.follow(user2, user) +      {:ok, activity} = CommonAPI.post(user, %{status: "super hot take"}) +      {:ok, _} = CommonAPI.add_mute(user2, activity) + +      assert_receive {:render_with_user, _, _, ^activity} +      assert Streamer.filtered_by_user?(user2, activity) +    end    end    describe "direct streams" do -    setup do -      :ok -    end +    setup do: oauth_access(["read"]) -    test "it sends conversation update to the 'direct' stream", %{} do -      user = insert(:user) +    test "it sends conversation update to the 'direct' stream", %{user: user, token: oauth_token} do        another_user = insert(:user) -      Streamer.get_topic_and_add_socket("direct", user) +      Streamer.get_topic_and_add_socket("direct", user, oauth_token)        {:ok, _create_activity} =          CommonAPI.post(another_user, %{ @@ -602,11 +696,11 @@ defmodule Pleroma.Web.StreamerTest do        assert last_status["pleroma"]["direct_conversation_id"] == participation.id      end -    test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted" do -      user = insert(:user) +    test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted", +         %{user: user, token: oauth_token} do        another_user = insert(:user) -      Streamer.get_topic_and_add_socket("direct", user) +      Streamer.get_topic_and_add_socket("direct", user, oauth_token)        {:ok, create_activity} =          CommonAPI.post(another_user, %{ @@ -629,10 +723,12 @@ defmodule Pleroma.Web.StreamerTest do        refute_receive _      end -    test "it sends conversation update to the 'direct' stream when a message is deleted" do -      user = insert(:user) +    test "it sends conversation update to the 'direct' stream when a message is deleted", %{ +      user: user, +      token: oauth_token +    } do        another_user = insert(:user) -      Streamer.get_topic_and_add_socket("direct", user) +      Streamer.get_topic_and_add_socket("direct", user, oauth_token)        {:ok, create_activity} =          CommonAPI.post(another_user, %{ diff --git a/test/web/twitter_api/password_controller_test.exs b/test/web/twitter_api/password_controller_test.exs index 231a46c67..a5e9e2178 100644 --- a/test/web/twitter_api/password_controller_test.exs +++ b/test/web/twitter_api/password_controller_test.exs @@ -37,7 +37,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do      test "it returns HTTP 200", %{conn: conn} do        user = insert(:user)        {:ok, token} = PasswordResetToken.create_token(user) -      {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{}) +      {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})        params = %{          "password" => "test", @@ -62,7 +62,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do        user = insert(:user, password_reset_pending: true)        {:ok, token} = PasswordResetToken.create_token(user) -      {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{}) +      {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})        params = %{          "password" => "test", diff --git a/test/web/twitter_api/remote_follow_controller_test.exs b/test/web/twitter_api/remote_follow_controller_test.exs index f7e54c26a..3852c7ce9 100644 --- a/test/web/twitter_api/remote_follow_controller_test.exs +++ b/test/web/twitter_api/remote_follow_controller_test.exs @@ -227,7 +227,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do            }          ) -      {:ok, %{token: token}} = MFA.Token.create_token(user) +      {:ok, %{token: token}} = MFA.Token.create(user)        user2 = insert(:user)        otp_token = TOTP.generate_token(otp_secret) @@ -256,7 +256,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do            }          ) -      {:ok, %{token: token}} = MFA.Token.create_token(user) +      {:ok, %{token: token}} = MFA.Token.create(user)        user2 = insert(:user)        otp_token = TOTP.generate_token(TOTP.generate_secret()) diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index d164127ee..60f2fb052 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -21,170 +21,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do    setup do: clear_config([:instance])    setup do: clear_config([:frontend_configurations, :pleroma_fe]) -  describe "POST /api/pleroma/follow_import" do -    setup do: oauth_access(["follow"]) - -    test "it returns HTTP 200", %{conn: conn} do -      user2 = insert(:user) - -      response = -        conn -        |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"}) -        |> json_response(:ok) - -      assert response == "job started" -    end - -    test "it imports follow lists from file", %{user: user1, conn: conn} do -      user2 = insert(:user) - -      with_mocks([ -        {File, [], -         read!: fn "follow_list.txt" -> -           "Account address,Show boosts\n#{user2.ap_id},true" -         end} -      ]) do -        response = -          conn -          |> post("/api/pleroma/follow_import", %{"list" => %Plug.Upload{path: "follow_list.txt"}}) -          |> json_response(:ok) - -        assert response == "job started" - -        assert ObanHelpers.member?( -                 %{ -                   "op" => "follow_import", -                   "follower_id" => user1.id, -                   "followed_identifiers" => [user2.ap_id] -                 }, -                 all_enqueued(worker: Pleroma.Workers.BackgroundWorker) -               ) -      end -    end - -    test "it imports new-style mastodon follow lists", %{conn: conn} do -      user2 = insert(:user) - -      response = -        conn -        |> post("/api/pleroma/follow_import", %{ -          "list" => "Account address,Show boosts\n#{user2.ap_id},true" -        }) -        |> json_response(:ok) - -      assert response == "job started" -    end - -    test "requires 'follow' or 'write:follows' permissions" do -      token1 = insert(:oauth_token, scopes: ["read", "write"]) -      token2 = insert(:oauth_token, scopes: ["follow"]) -      token3 = insert(:oauth_token, scopes: ["something"]) -      another_user = insert(:user) - -      for token <- [token1, token2, token3] do -        conn = -          build_conn() -          |> put_req_header("authorization", "Bearer #{token.token}") -          |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) - -        if token == token3 do -          assert %{"error" => "Insufficient permissions: follow | write:follows."} == -                   json_response(conn, 403) -        else -          assert json_response(conn, 200) -        end -      end -    end - -    test "it imports follows with different nickname variations", %{conn: conn} do -      [user2, user3, user4, user5, user6] = insert_list(5, :user) - -      identifiers = -        [ -          user2.ap_id, -          user3.nickname, -          "  ", -          "@" <> user4.nickname, -          user5.nickname <> "@localhost", -          "@" <> user6.nickname <> "@localhost" -        ] -        |> Enum.join("\n") - -      response = -        conn -        |> post("/api/pleroma/follow_import", %{"list" => identifiers}) -        |> json_response(:ok) - -      assert response == "job started" -      assert [{:ok, job_result}] = ObanHelpers.perform_all() -      assert job_result == [user2, user3, user4, user5, user6] -    end -  end - -  describe "POST /api/pleroma/blocks_import" do -    # Note: "follow" or "write:blocks" permission is required -    setup do: oauth_access(["write:blocks"]) - -    test "it returns HTTP 200", %{conn: conn} do -      user2 = insert(:user) - -      response = -        conn -        |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"}) -        |> json_response(:ok) - -      assert response == "job started" -    end - -    test "it imports blocks users from file", %{user: user1, conn: conn} do -      user2 = insert(:user) -      user3 = insert(:user) - -      with_mocks([ -        {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end} -      ]) do -        response = -          conn -          |> post("/api/pleroma/blocks_import", %{"list" => %Plug.Upload{path: "blocks_list.txt"}}) -          |> json_response(:ok) - -        assert response == "job started" - -        assert ObanHelpers.member?( -                 %{ -                   "op" => "blocks_import", -                   "blocker_id" => user1.id, -                   "blocked_identifiers" => [user2.ap_id, user3.ap_id] -                 }, -                 all_enqueued(worker: Pleroma.Workers.BackgroundWorker) -               ) -      end -    end - -    test "it imports blocks with different nickname variations", %{conn: conn} do -      [user2, user3, user4, user5, user6] = insert_list(5, :user) - -      identifiers = -        [ -          user2.ap_id, -          user3.nickname, -          "@" <> user4.nickname, -          user5.nickname <> "@localhost", -          "@" <> user6.nickname <> "@localhost" -        ] -        |> Enum.join(" ") - -      response = -        conn -        |> post("/api/pleroma/blocks_import", %{"list" => identifiers}) -        |> json_response(:ok) - -      assert response == "job started" -      assert [{:ok, job_result}] = ObanHelpers.perform_all() -      assert job_result == [user2, user3, user4, user5, user6] -    end -  end -    describe "PUT /api/pleroma/notification_settings" do      setup do: oauth_access(["write:accounts"])  | 
