diff options
| author | Maxim Filippov <colixer@gmail.com> | 2019-10-07 15:41:41 +0300 | 
|---|---|---|
| committer | Maxim Filippov <colixer@gmail.com> | 2019-10-07 15:41:41 +0300 | 
| commit | 35068baf65f1be9ac4e5ae8d08222244ae823fcc (patch) | |
| tree | 0ed0b88fd100fb3df83400c147ab9a6a88d53c73 /test | |
| parent | 7aceaa517be7b109a9acc15fb4914535b536b66c (diff) | |
| parent | 0a99f1e8c5551dcf170722e5087a0401b2d907af (diff) | |
| download | pleroma-35068baf65f1be9ac4e5ae8d08222244ae823fcc.tar.gz pleroma-35068baf65f1be9ac4e5ae8d08222244ae823fcc.zip | |
Merge branch 'develop' into feature/reports-groups-and-multiple-state-update
Diffstat (limited to 'test')
31 files changed, 1035 insertions, 471 deletions
| diff --git a/test/conversation/participation_test.exs b/test/conversation/participation_test.exs index a27167d42..f430bdf75 100644 --- a/test/conversation/participation_test.exs +++ b/test/conversation/participation_test.exs @@ -6,6 +6,7 @@ defmodule Pleroma.Conversation.ParticipationTest do    use Pleroma.DataCase    import Pleroma.Factory    alias Pleroma.Conversation.Participation +  alias Pleroma.User    alias Pleroma.Web.CommonAPI    test "getting a participation will also preload things" do @@ -30,6 +31,8 @@ defmodule Pleroma.Conversation.ParticipationTest do      {:ok, activity} =        CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"}) +    user = User.get_cached_by_id(user.id) +    other_user = User.get_cached_by_id(user.id)      [participation] = Participation.for_user(user)      participation = Pleroma.Repo.preload(participation, :recipients) @@ -155,6 +158,7 @@ defmodule Pleroma.Conversation.ParticipationTest do      [participation] = Participation.for_user_with_last_activity_id(user)      participation = Repo.preload(participation, :recipients) +    user = User.get_cached_by_id(user.id)      assert participation.recipients |> length() == 1      assert user in participation.recipients diff --git a/test/emails/admin_email_test.exs b/test/emails/admin_email_test.exs index 31eac5f12..ad89f9213 100644 --- a/test/emails/admin_email_test.exs +++ b/test/emails/admin_email_test.exs @@ -19,8 +19,8 @@ defmodule Pleroma.Emails.AdminEmailTest do        AdminEmail.report(to_user, reporter, account, [%{name: "Test", id: "12"}], "Test comment")      status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, "12") -    reporter_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, reporter.nickname) -    account_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, account.nickname) +    reporter_url = Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, reporter.id) +    account_url = Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, account.id)      assert res.to == [{to_user.name, to_user.email}]      assert res.from == {config[:name], config[:notify_email]} diff --git a/test/fixtures/bogus-mastodon-announce.json b/test/fixtures/bogus-mastodon-announce.json new file mode 100644 index 000000000..0485b80b9 --- /dev/null +++ b/test/fixtures/bogus-mastodon-announce.json @@ -0,0 +1,43 @@ +{ +  "type": "Announce", +  "to": [ +    "https://www.w3.org/ns/activitystreams#Public" +  ], +  "published": "2018-02-17T19:39:15Z", +  "object": { +    "type": "Note", +    "id": "https://mastodon.social/users/emelie/statuses/101849165031453404", +    "attributedTo": "https://mastodon.social/users/emelie", +    "content": "this is a public toot", +    "to": [ +      "https://www.w3.org/ns/activitystreams#Public" +    ], +    "cc": [ +      "https://mastodon.social/users/emelie", +      "https://mastodon.social/users/emelie/followers" +    ] +  }, +  "id": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "cc": [ +    "http://mastodon.example.org/users/admin", +    "http://mastodon.example.org/users/admin/followers" +  ], +  "atomUri": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "actor": "http://mastodon.example.org/users/admin", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "toot": "http://joinmastodon.org/ns#", +      "sensitive": "as:sensitive", +      "ostatus": "http://ostatus.org#", +      "movedTo": "as:movedTo", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +      "conversation": "ostatus:conversation", +      "atomUri": "ostatus:atomUri", +      "Hashtag": "as:Hashtag", +      "Emoji": "toot:Emoji" +    } +  ] +} diff --git a/test/fixtures/mastodon-announce-private.json b/test/fixtures/mastodon-announce-private.json new file mode 100644 index 000000000..9b868b13d --- /dev/null +++ b/test/fixtures/mastodon-announce-private.json @@ -0,0 +1,35 @@ +{ +  "type": "Announce", +  "to": [ +    "http://mastodon.example.org/users/admin/followers" +  ], +  "published": "2018-02-17T19:39:15Z", +  "object": { +    "type": "Note", +    "id": "http://mastodon.example.org/@admin/99541947525187368", +    "attributedTo": "http://mastodon.example.org/users/admin", +    "content": "this is a private toot", +    "to": [ +      "http://mastodon.example.org/users/admin/followers" +    ] +  }, +  "id": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "atomUri": "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity", +  "actor": "http://mastodon.example.org/users/admin", +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "toot": "http://joinmastodon.org/ns#", +      "sensitive": "as:sensitive", +      "ostatus": "http://ostatus.org#", +      "movedTo": "as:movedTo", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +      "conversation": "ostatus:conversation", +      "atomUri": "ostatus:atomUri", +      "Hashtag": "as:Hashtag", +      "Emoji": "toot:Emoji" +    } +  ] +} diff --git a/test/healthcheck_test.exs b/test/healthcheck_test.exs index 6bb8d5b7f..66d5026ff 100644 --- a/test/healthcheck_test.exs +++ b/test/healthcheck_test.exs @@ -9,7 +9,14 @@ defmodule Pleroma.HealthcheckTest do    test "system_info/0" do      result = Healthcheck.system_info() |> Map.from_struct() -    assert Map.keys(result) == [:active, :healthy, :idle, :memory_used, :pool_size] +    assert Map.keys(result) == [ +             :active, +             :healthy, +             :idle, +             :job_queue_stats, +             :memory_used, +             :pool_size +           ]    end    describe "check_health/1" do diff --git a/test/job_queue_monitor_test.exs b/test/job_queue_monitor_test.exs new file mode 100644 index 000000000..17c6f3246 --- /dev/null +++ b/test/job_queue_monitor_test.exs @@ -0,0 +1,70 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.JobQueueMonitorTest do +  use ExUnit.Case, async: true + +  alias Pleroma.JobQueueMonitor + +  @success {:process_event, :success, 1337, +            %{ +              args: %{"op" => "refresh_subscriptions"}, +              attempt: 1, +              id: 339, +              max_attempts: 5, +              queue: "federator_outgoing", +              worker: "Pleroma.Workers.SubscriberWorker" +            }} + +  @failure {:process_event, :failure, 22_521_134, +            %{ +              args: %{"op" => "force_password_reset", "user_id" => "9nJG6n6Nbu7tj9GJX6"}, +              attempt: 1, +              error: %RuntimeError{message: "oops"}, +              id: 345, +              kind: :exception, +              max_attempts: 1, +              queue: "background", +              stack: [ +                {Pleroma.Workers.BackgroundWorker, :perform, 2, +                 [file: 'lib/pleroma/workers/background_worker.ex', line: 31]}, +                {Oban.Queue.Executor, :safe_call, 1, +                 [file: 'lib/oban/queue/executor.ex', line: 42]}, +                {:timer, :tc, 3, [file: 'timer.erl', line: 197]}, +                {Oban.Queue.Executor, :call, 2, [file: 'lib/oban/queue/executor.ex', line: 23]}, +                {Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]}, +                {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]} +              ], +              worker: "Pleroma.Workers.BackgroundWorker" +            }} + +  test "stats/0" do +    assert %{processed_jobs: _, queues: _, workers: _} = JobQueueMonitor.stats() +  end + +  test "handle_cast/2" do +    state = %{workers: %{}, queues: %{}, processed_jobs: 0} + +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@success, state) +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@failure, state) +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@success, state) +    assert {:noreply, state} = JobQueueMonitor.handle_cast(@failure, state) + +    assert state == %{ +             processed_jobs: 4, +             queues: %{ +               "background" => %{failure: 2, processed_jobs: 2, success: 0}, +               "federator_outgoing" => %{failure: 0, processed_jobs: 2, success: 2} +             }, +             workers: %{ +               "Pleroma.Workers.BackgroundWorker" => %{ +                 "force_password_reset" => %{failure: 2, processed_jobs: 2, success: 0} +               }, +               "Pleroma.Workers.SubscriberWorker" => %{ +                 "refresh_subscriptions" => %{failure: 0, processed_jobs: 2, success: 2} +               } +             } +           } +  end +end diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs index 6a13ea811..be6d1340b 100644 --- a/test/plugs/oauth_scopes_plug_test.exs +++ b/test/plugs/oauth_scopes_plug_test.exs @@ -5,24 +5,48 @@  defmodule Pleroma.Plugs.OAuthScopesPlugTest do    use Pleroma.Web.ConnCase, async: true +  alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug    alias Pleroma.Plugs.OAuthScopesPlug    alias Pleroma.Repo +  import Mock    import Pleroma.Factory -  test "proceeds with no op if `assigns[:token]` is nil", %{conn: conn} do -    conn = -      conn -      |> assign(:user, insert(:user)) -      |> OAuthScopesPlug.call(%{scopes: ["read"]}) +  setup_with_mocks([{EnsurePublicOrAuthenticatedPlug, [], [call: fn conn, _ -> conn end]}]) do +    :ok +  end -    refute conn.halted -    assert conn.assigns[:user] +  describe "when `assigns[:token]` is nil, " do +    test "with :skip_instance_privacy_check option, proceeds with no op", %{conn: conn} do +      conn = +        conn +        |> assign(:user, insert(:user)) +        |> OAuthScopesPlug.call(%{scopes: ["read"], skip_instance_privacy_check: true}) + +      refute conn.halted +      assert conn.assigns[:user] + +      refute called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) +    end + +    test "without :skip_instance_privacy_check option, calls EnsurePublicOrAuthenticatedPlug", %{ +      conn: conn +    } do +      conn = +        conn +        |> assign(:user, insert(:user)) +        |> OAuthScopesPlug.call(%{scopes: ["read"]}) + +      refute conn.halted +      assert conn.assigns[:user] + +      assert called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) +    end    end -  test "proceeds with no op if `token.scopes` fulfill specified 'any of' conditions", %{ -    conn: conn -  } do +  test "if `token.scopes` fulfills specified 'any of' conditions, " <> +         "proceeds with no op", +       %{conn: conn} do      token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user)      conn = @@ -35,9 +59,9 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do      assert conn.assigns[:user]    end -  test "proceeds with no op if `token.scopes` fulfill specified 'all of' conditions", %{ -    conn: conn -  } do +  test "if `token.scopes` fulfills specified 'all of' conditions, " <> +         "proceeds with no op", +       %{conn: conn} do      token = insert(:oauth_token, scopes: ["scope1", "scope2", "scope3"]) |> Repo.preload(:user)      conn = @@ -50,73 +74,154 @@ defmodule Pleroma.Plugs.OAuthScopesPlugTest do      assert conn.assigns[:user]    end -  test "proceeds with cleared `assigns[:user]` if `token.scopes` doesn't fulfill specified 'any of' conditions " <> -         "and `fallback: :proceed_unauthenticated` option is specified", -       %{conn: conn} do -    token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user) +  describe "with `fallback: :proceed_unauthenticated` option, " do +    test "if `token.scopes` doesn't fulfill specified 'any of' conditions, " <> +           "clears `assigns[:user]` and calls EnsurePublicOrAuthenticatedPlug", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user) + +      conn = +        conn +        |> assign(:user, token.user) +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{scopes: ["follow"], fallback: :proceed_unauthenticated}) + +      refute conn.halted +      refute conn.assigns[:user] + +      assert called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) +    end + +    test "if `token.scopes` doesn't fulfill specified 'all of' conditions, " <> +           "clears `assigns[:user] and calls EnsurePublicOrAuthenticatedPlug", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user) + +      conn = +        conn +        |> assign(:user, token.user) +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{ +          scopes: ["read", "follow"], +          op: :&, +          fallback: :proceed_unauthenticated +        }) + +      refute conn.halted +      refute conn.assigns[:user] + +      assert called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) +    end + +    test "with :skip_instance_privacy_check option, " <> +           "if `token.scopes` doesn't fulfill specified conditions, " <> +           "clears `assigns[:user]` and does not call EnsurePublicOrAuthenticatedPlug", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read:statuses", "write"]) |> Repo.preload(:user) + +      conn = +        conn +        |> assign(:user, token.user) +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{ +          scopes: ["read"], +          fallback: :proceed_unauthenticated, +          skip_instance_privacy_check: true +        }) + +      refute conn.halted +      refute conn.assigns[:user] + +      refute called(EnsurePublicOrAuthenticatedPlug.call(conn, :_)) +    end +  end -    conn = -      conn -      |> assign(:user, token.user) -      |> assign(:token, token) -      |> OAuthScopesPlug.call(%{scopes: ["follow"], fallback: :proceed_unauthenticated}) +  describe "without :fallback option, " do +    test "if `token.scopes` does not fulfill specified 'any of' conditions, " <> +           "returns 403 and halts", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read", "write"]) +      any_of_scopes = ["follow"] -    refute conn.halted -    refute conn.assigns[:user] -  end +      conn = +        conn +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{scopes: any_of_scopes}) -  test "proceeds with cleared `assigns[:user]` if `token.scopes` doesn't fulfill specified 'all of' conditions " <> -         "and `fallback: :proceed_unauthenticated` option is specified", -       %{conn: conn} do -    token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user) +      assert conn.halted +      assert 403 == conn.status -    conn = -      conn -      |> assign(:user, token.user) -      |> assign(:token, token) -      |> OAuthScopesPlug.call(%{ -        scopes: ["read", "follow"], -        op: :&, -        fallback: :proceed_unauthenticated -      }) +      expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, ", ")}." +      assert Jason.encode!(%{error: expected_error}) == conn.resp_body +    end -    refute conn.halted -    refute conn.assigns[:user] -  end +    test "if `token.scopes` does not fulfill specified 'all of' conditions, " <> +           "returns 403 and halts", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read", "write"]) +      all_of_scopes = ["write", "follow"] -  test "returns 403 and halts in case of no :fallback option and `token.scopes` not fulfilling specified 'any of' conditions", -       %{conn: conn} do -    token = insert(:oauth_token, scopes: ["read", "write"]) -    any_of_scopes = ["follow"] +      conn = +        conn +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&}) -    conn = -      conn -      |> assign(:token, token) -      |> OAuthScopesPlug.call(%{scopes: any_of_scopes}) +      assert conn.halted +      assert 403 == conn.status -    assert conn.halted -    assert 403 == conn.status +      expected_error = +        "Insufficient permissions: #{Enum.join(all_of_scopes -- token.scopes, ", ")}." -    expected_error = "Insufficient permissions: #{Enum.join(any_of_scopes, ", ")}." -    assert Jason.encode!(%{error: expected_error}) == conn.resp_body +      assert Jason.encode!(%{error: expected_error}) == conn.resp_body +    end    end -  test "returns 403 and halts in case of no :fallback option and `token.scopes` not fulfilling specified 'all of' conditions", -       %{conn: conn} do -    token = insert(:oauth_token, scopes: ["read", "write"]) -    all_of_scopes = ["write", "follow"] +  describe "with hierarchical scopes, " do +    test "if `token.scopes` fulfills specified 'any of' conditions, " <> +           "proceeds with no op", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["read", "write"]) |> Repo.preload(:user) + +      conn = +        conn +        |> assign(:user, token.user) +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{scopes: ["read:something"]}) + +      refute conn.halted +      assert conn.assigns[:user] +    end + +    test "if `token.scopes` fulfills specified 'all of' conditions, " <> +           "proceeds with no op", +         %{conn: conn} do +      token = insert(:oauth_token, scopes: ["scope1", "scope2", "scope3"]) |> Repo.preload(:user) + +      conn = +        conn +        |> assign(:user, token.user) +        |> assign(:token, token) +        |> OAuthScopesPlug.call(%{scopes: ["scope1:subscope", "scope2:subscope"], op: :&}) + +      refute conn.halted +      assert conn.assigns[:user] +    end +  end -    conn = -      conn -      |> assign(:token, token) -      |> OAuthScopesPlug.call(%{scopes: all_of_scopes, op: :&}) +  describe "filter_descendants/2" do +    test "filters scopes which directly match or are ancestors of supported scopes" do +      f = fn scopes, supported_scopes -> +        OAuthScopesPlug.filter_descendants(scopes, supported_scopes) +      end + +      assert f.(["read", "follow"], ["write", "read"]) == ["read"] -    assert conn.halted -    assert 403 == conn.status +      assert f.(["read", "write:something", "follow"], ["write", "read"]) == +               ["read", "write:something"] -    expected_error = -      "Insufficient permissions: #{Enum.join(all_of_scopes -- token.scopes, ", ")}." +      assert f.(["admin:read"], ["write", "read"]) == [] -    assert Jason.encode!(%{error: expected_error}) == conn.resp_body +      assert f.(["admin:read"], ["write", "admin"]) == ["admin:read"] +    end    end  end diff --git a/test/signature_test.exs b/test/signature_test.exs index d5bf63d7d..96c8ba07a 100644 --- a/test/signature_test.exs +++ b/test/signature_test.exs @@ -80,7 +80,7 @@ defmodule Pleroma.SignatureTest do        user =          insert(:user, %{            ap_id: "https://mastodon.social/users/lambadalambda", -          info: %{keys: @private_key} +          keys: @private_key          })        assert Signature.sign( @@ -94,8 +94,7 @@ defmodule Pleroma.SignatureTest do      end      test "it returns error" do -      user = -        insert(:user, %{ap_id: "https://mastodon.social/users/lambadalambda", info: %{keys: ""}}) +      user = insert(:user, %{ap_id: "https://mastodon.social/users/lambadalambda", keys: ""})        assert Signature.sign(                 user, diff --git a/test/support/factory.ex b/test/support/factory.ex index 4f3244025..b180844cd 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -324,6 +324,7 @@ defmodule Pleroma.Factory do      %Pleroma.Web.OAuth.Token{        token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(), +      scopes: ["read"],        refresh_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),        user: build(:user),        app_id: oauth_app.id, diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 5506c0626..b825a9307 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -46,6 +46,14 @@ defmodule HttpRequestMock do       }}    end +  def get("https://mastodon.social/users/emelie/statuses/101849165031453404", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 404, +       body: "" +     }} +  end +    def get("https://mastodon.social/users/emelie", _, _, _) do      {:ok,       %Tesla.Env{ @@ -349,6 +357,14 @@ defmodule HttpRequestMock do       }}    end +  def get("http://mastodon.example.org/@admin/99541947525187368", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 404, +       body: "" +     }} +  end +    def get("https://shitposter.club/notice/7369654", _, _, _) do      {:ok,       %Tesla.Env{ diff --git a/test/user_test.exs b/test/user_test.exs index 126bd69e8..019e7b400 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -515,7 +515,7 @@ defmodule Pleroma.UserTest do      user = insert(:user)      assert User.ap_id(user) == -             Pleroma.Web.Router.Helpers.o_status_url( +             Pleroma.Web.Router.Helpers.feed_url(                 Pleroma.Web.Endpoint,                 :feed_redirect,                 user.nickname @@ -526,7 +526,7 @@ defmodule Pleroma.UserTest do      user = insert(:user)      assert User.ap_followers(user) == -             Pleroma.Web.Router.Helpers.o_status_url( +             Pleroma.Web.Router.Helpers.feed_url(                 Pleroma.Web.Endpoint,                 :feed_redirect,                 user.nickname @@ -1457,15 +1457,15 @@ defmodule Pleroma.UserTest do    describe "ensure_keys_present" do      test "it creates keys for a user and stores them in info" do        user = insert(:user) -      refute is_binary(user.info.keys) +      refute is_binary(user.keys)        {:ok, user} = User.ensure_keys_present(user) -      assert is_binary(user.info.keys) +      assert is_binary(user.keys)      end      test "it doesn't create keys if there already are some" do -      user = insert(:user, %{info: %{keys: "xxx"}}) +      user = insert(:user, keys: "xxx")        {:ok, user} = User.ensure_keys_present(user) -      assert user.info.keys == "xxx" +      assert user.keys == "xxx"      end    end @@ -1725,4 +1725,61 @@ defmodule Pleroma.UserTest do      assert %{info: %{hide_follows: true}} = Repo.get(User, user.id)      assert {:ok, %{info: %{hide_follows: true}}} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")    end + +  describe "get_cached_by_nickname_or_id" do +    setup do +      limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content]) +      local_user = insert(:user) +      remote_user = insert(:user, nickname: "nickname@example.com", local: false) + +      on_exit(fn -> +        Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local_content) +      end) + +      [local_user: local_user, remote_user: remote_user] +    end + +    test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{ +      remote_user: remote_user +    } do +      Pleroma.Config.put([:instance, :limit_to_local_content], false) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id) + +      Pleroma.Config.put([:instance, :limit_to_local_content], true) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id) + +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id) +    end + +    test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated", +         %{remote_user: remote_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname) +    end + +    test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated", +         %{remote_user: remote_user, local_user: local_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user) +    end + +    test "disallows getting remote users by nickname when :limit_to_local_content is set to true", +         %{remote_user: remote_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], true) +      assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname) +    end + +    test "allows getting local users by nickname no matter what :limit_to_local_content is set to", +         %{local_user: local_user} do +      Pleroma.Config.put([:instance, :limit_to_local_content], false) +      assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) + +      Pleroma.Config.put([:instance, :limit_to_local_content], true) +      assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) + +      Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated) +      assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) +    end +  end  end diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index 1ffa91b70..6a3e48b5e 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -225,69 +225,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do      end    end -  describe "/object/:uuid/likes" do -    setup do -      like = insert(:like_activity) -      like_object_ap_id = Object.normalize(like).data["id"] - -      uuid = -        like_object_ap_id -        |> String.split("/") -        |> List.last() - -      [id: like.data["id"], uuid: uuid] -    end - -    test "it returns the like activities in a collection", %{conn: conn, id: id, uuid: uuid} do -      result = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/objects/#{uuid}/likes") -        |> json_response(200) - -      assert List.first(result["first"]["orderedItems"])["id"] == id -      assert result["type"] == "OrderedCollection" -      assert result["totalItems"] == 1 -      refute result["first"]["next"] -    end - -    test "it does not crash when page number is exceeded total pages", %{conn: conn, uuid: uuid} do -      result = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/objects/#{uuid}/likes?page=2") -        |> json_response(200) - -      assert result["type"] == "OrderedCollectionPage" -      assert result["totalItems"] == 1 -      refute result["next"] -      assert Enum.empty?(result["orderedItems"]) -    end - -    test "it contains the next key when likes count is more than 10", %{conn: conn} do -      note = insert(:note_activity) -      insert_list(11, :like_activity, note_activity: note) - -      uuid = -        note -        |> Object.normalize() -        |> Map.get(:data) -        |> Map.get("id") -        |> String.split("/") -        |> List.last() - -      result = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/objects/#{uuid}/likes?page=1") -        |> json_response(200) - -      assert result["totalItems"] == 11 -      assert length(result["orderedItems"]) == 10 -      assert result["next"] -    end -  end -    describe "/activities/:uuid" do      test "it returns a json representation of the activity", %{conn: conn} do        activity = insert(:note_activity) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index f29497847..c9f2a92e7 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -811,10 +811,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        {:ok, like_activity, object} = ActivityPub.like(user, object)        assert object.data["like_count"] == 1 -      {:ok, _, _, object} = ActivityPub.unlike(user, object) +      {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)        assert object.data["like_count"] == 0        assert Activity.get_by_id(like_activity.id) == nil +      assert note_activity.actor in unlike_activity.recipients      end    end @@ -890,7 +891,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert unannounce_activity.data["to"] == [                 User.ap_followers(user), -               announce_activity.data["actor"] +               object.data["actor"]               ]        assert unannounce_activity.data["type"] == "Undo" diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs index 7203b27da..df0f223f8 100644 --- a/test/web/activity_pub/mrf/simple_policy_test.exs +++ b/test/web/activity_pub/mrf/simple_policy_test.exs @@ -236,7 +236,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        assert SimplePolicy.filter(remote_message) == {:ok, remote_message}      end -    test "has a matching host" do +    test "activity has a matching host" do        Config.put([:mrf_simple, :reject], ["remote.instance"])        remote_message = build_remote_message() @@ -244,13 +244,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        assert SimplePolicy.filter(remote_message) == {:reject, nil}      end -    test "match with wildcard domain" do +    test "activity matches with wildcard domain" do        Config.put([:mrf_simple, :reject], ["*.remote.instance"])        remote_message = build_remote_message()        assert SimplePolicy.filter(remote_message) == {:reject, nil}      end + +    test "actor has a matching host" do +      Config.put([:mrf_simple, :reject], ["remote.instance"]) + +      remote_user = build_remote_user() + +      assert SimplePolicy.filter(remote_user) == {:reject, nil} +    end    end    describe "when :accept" do @@ -264,7 +272,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        assert SimplePolicy.filter(remote_message) == {:ok, remote_message}      end -    test "is not empty but it doesn't have a matching host" do +    test "is not empty but activity doesn't have a matching host" do        Config.put([:mrf_simple, :accept], ["non.matching.remote"])        local_message = build_local_message() @@ -274,7 +282,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        assert SimplePolicy.filter(remote_message) == {:reject, nil}      end -    test "has a matching host" do +    test "activity has a matching host" do        Config.put([:mrf_simple, :accept], ["remote.instance"])        local_message = build_local_message() @@ -284,7 +292,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        assert SimplePolicy.filter(remote_message) == {:ok, remote_message}      end -    test "match with wildcard domain" do +    test "activity matches with wildcard domain" do        Config.put([:mrf_simple, :accept], ["*.remote.instance"])        local_message = build_local_message() @@ -293,6 +301,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        assert SimplePolicy.filter(local_message) == {:ok, local_message}        assert SimplePolicy.filter(remote_message) == {:ok, remote_message}      end + +    test "actor has a matching host" do +      Config.put([:mrf_simple, :accept], ["remote.instance"]) + +      remote_user = build_remote_user() + +      assert SimplePolicy.filter(remote_user) == {:ok, remote_user} +    end    end    describe "when :avatar_removal" do diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 6c208bdc0..50c0bfb84 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -442,6 +442,33 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id      end +    test "it works for incoming announces with an inlined activity" do +      data = +        File.read!("test/fixtures/mastodon-announce-private.json") +        |> Poison.decode!() + +      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +      assert data["actor"] == "http://mastodon.example.org/users/admin" +      assert data["type"] == "Announce" + +      assert data["id"] == +               "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" + +      object = Object.normalize(data["object"]) + +      assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368" +      assert object.data["content"] == "this is a private toot" +    end + +    test "it rejects incoming announces with an inlined activity from another origin" do +      data = +        File.read!("test/fixtures/bogus-mastodon-announce.json") +        |> Poison.decode!() + +      assert :error = Transmogrifier.handle_incoming(data) +    end +      test "it does not clobber the addressing on announce activities" do        user = insert(:user)        {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) @@ -546,6 +573,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data) +      assert data["id"] == update_data["id"] +        user = User.get_cached_by_ap_id(data["actor"])        assert user.name == "gargle" diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index b1c1d6f71..c57ea7eb9 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -106,11 +106,13 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user)        like_activity = insert(:like_activity, data_attrs: %{"context" => "test context"}) +      object = Object.normalize(like_activity.data["object"]) +        assert Utils.make_unlike_data(user, like_activity, nil) == %{                 "type" => "Undo",                 "actor" => user.ap_id,                 "object" => like_activity.data, -               "to" => [user.follower_address, like_activity.data["actor"]], +               "to" => [user.follower_address, object.data["actor"]],                 "cc" => [Pleroma.Constants.as_public()],                 "context" => like_activity.data["context"]               } @@ -119,7 +121,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do                 "type" => "Undo",                 "actor" => user.ap_id,                 "object" => like_activity.data, -               "to" => [user.follower_address, like_activity.data["actor"]], +               "to" => [user.follower_address, object.data["actor"]],                 "cc" => [Pleroma.Constants.as_public()],                 "context" => like_activity.data["context"],                 "id" => "9mJEZK0tky1w2xD2vY" diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index c57fdb6af..2b34f1d1e 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -14,6 +14,8 @@ defmodule Pleroma.Web.CommonAPITest do    import Pleroma.Factory +  require Pleroma.Constants +    clear_config([:instance, :safe_dm_mentions])    clear_config([:instance, :limit])    clear_config([:instance, :max_pinned_statuses]) @@ -96,11 +98,13 @@ defmodule Pleroma.Web.CommonAPITest do    test "it adds emoji when updating profiles" do      user = insert(:user, %{name: ":firefox:"}) -    CommonAPI.update(user) +    {:ok, activity} = CommonAPI.update(user)      user = User.get_cached_by_ap_id(user.ap_id)      [firefox] = user.info.source_data["tag"]      assert firefox["name"] == ":firefox:" + +    assert Pleroma.Constants.as_public() in activity.recipients    end    describe "posting" do diff --git a/test/web/feed/feed_controller_test.exs b/test/web/feed/feed_controller_test.exs new file mode 100644 index 000000000..1f44eae20 --- /dev/null +++ b/test/web/feed/feed_controller_test.exs @@ -0,0 +1,227 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Feed.FeedControllerTest do +  use Pleroma.Web.ConnCase + +  import Pleroma.Factory + +  alias Pleroma.Object +  alias Pleroma.User + +  test "gets a feed", %{conn: conn} do +    activity = insert(:note_activity) + +    note = +      insert(:note, +        data: %{ +          "attachment" => [ +            %{ +              "url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}] +            } +          ], +          "inReplyTo" => activity.data["id"] +        } +      ) + +    note_activity = insert(:note_activity, note: note) +    object = Object.normalize(note_activity) +    user = User.get_cached_by_ap_id(note_activity.data["actor"]) + +    conn = +      conn +      |> put_req_header("content-type", "application/atom+xml") +      |> get("/users/#{user.nickname}/feed.atom") + +    assert response(conn, 200) =~ object.data["content"] +  end + +  test "returns 404 for a missing feed", %{conn: conn} do +    conn = +      conn +      |> put_req_header("content-type", "application/atom+xml") +      |> get("/users/nonexisting/feed.atom") + +    assert response(conn, 404) +  end + +  describe "feed_redirect" do +    test "undefined format. it redirects to feed", %{conn: conn} do +      note_activity = insert(:note_activity) +      user = User.get_cached_by_ap_id(note_activity.data["actor"]) + +      response = +        conn +        |> put_req_header("accept", "application/xml") +        |> get("/users/#{user.nickname}") +        |> response(302) + +      assert response == +               "<html><body>You are being <a href=\"#{Pleroma.Web.base_url()}/users/#{ +                 user.nickname +               }/feed.atom\">redirected</a>.</body></html>" +    end + +    test "undefined format. it returns error when user not found", %{conn: conn} do +      response = +        conn +        |> put_req_header("accept", "application/xml") +        |> get("/users/jimm") +        |> response(404) + +      assert response == ~S({"error":"Not found"}) +    end + +    test "activity+json format. it redirects on actual feed of user", %{conn: conn} do +      note_activity = insert(:note_activity) +      user = User.get_cached_by_ap_id(note_activity.data["actor"]) + +      response = +        conn +        |> put_req_header("accept", "application/activity+json") +        |> get("/users/#{user.nickname}") +        |> json_response(200) + +      assert response["endpoints"] == %{ +               "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize", +               "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps", +               "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token", +               "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox", +               "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media" +             } + +      assert response["@context"] == [ +               "https://www.w3.org/ns/activitystreams", +               "http://localhost:4001/schemas/litepub-0.1.jsonld", +               %{"@language" => "und"} +             ] + +      assert Map.take(response, [ +               "followers", +               "following", +               "id", +               "inbox", +               "manuallyApprovesFollowers", +               "name", +               "outbox", +               "preferredUsername", +               "summary", +               "tag", +               "type", +               "url" +             ]) == %{ +               "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers", +               "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following", +               "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}", +               "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox", +               "manuallyApprovesFollowers" => false, +               "name" => user.name, +               "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox", +               "preferredUsername" => user.nickname, +               "summary" => user.bio, +               "tag" => [], +               "type" => "Person", +               "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}" +             } +    end + +    test "activity+json format. it returns error whe use not found", %{conn: conn} do +      response = +        conn +        |> put_req_header("accept", "application/activity+json") +        |> get("/users/jimm") +        |> json_response(404) + +      assert response == "Not found" +    end + +    test "json format. it redirects on actual feed of user", %{conn: conn} do +      note_activity = insert(:note_activity) +      user = User.get_cached_by_ap_id(note_activity.data["actor"]) + +      response = +        conn +        |> put_req_header("accept", "application/json") +        |> get("/users/#{user.nickname}") +        |> json_response(200) + +      assert response["endpoints"] == %{ +               "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize", +               "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps", +               "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token", +               "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox", +               "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media" +             } + +      assert response["@context"] == [ +               "https://www.w3.org/ns/activitystreams", +               "http://localhost:4001/schemas/litepub-0.1.jsonld", +               %{"@language" => "und"} +             ] + +      assert Map.take(response, [ +               "followers", +               "following", +               "id", +               "inbox", +               "manuallyApprovesFollowers", +               "name", +               "outbox", +               "preferredUsername", +               "summary", +               "tag", +               "type", +               "url" +             ]) == %{ +               "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers", +               "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following", +               "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}", +               "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox", +               "manuallyApprovesFollowers" => false, +               "name" => user.name, +               "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox", +               "preferredUsername" => user.nickname, +               "summary" => user.bio, +               "tag" => [], +               "type" => "Person", +               "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}" +             } +    end + +    test "json format. it returns error whe use not found", %{conn: conn} do +      response = +        conn +        |> put_req_header("accept", "application/json") +        |> get("/users/jimm") +        |> json_response(404) + +      assert response == "Not found" +    end + +    test "html format. it redirects on actual feed of user", %{conn: conn} do +      note_activity = insert(:note_activity) +      user = User.get_cached_by_ap_id(note_activity.data["actor"]) + +      response = +        conn +        |> get("/users/#{user.nickname}") +        |> response(200) + +      assert response == +               Fallback.RedirectController.redirector_with_meta( +                 conn, +                 %{user: user} +               ).resp_body +    end + +    test "html format. it returns error when user not found", %{conn: conn} do +      response = +        conn +        |> get("/users/jimm") +        |> json_response(404) + +      assert response == %{"error" => "Not found"} +    end +  end +end diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index 560f55137..618031b40 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -272,7 +272,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert user_response["pleroma"]["background_image"]      end -    test "requires 'write' permission", %{conn: conn} do +    test "requires 'write:accounts' permission", %{conn: conn} do        token1 = insert(:oauth_token, scopes: ["read"])        token2 = insert(:oauth_token, scopes: ["write", "follow"]) @@ -283,7 +283,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do            |> patch("/api/v1/accounts/update_credentials", %{})          if token == token1 do -          assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403) +          assert %{"error" => "Insufficient permissions: write:accounts."} == +                   json_response(conn, 403)          else            assert json_response(conn, 200)          end @@ -328,7 +329,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        account =          conn          |> assign(:user, user) -        |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})          |> json_response(200)        assert account["fields"] == [ @@ -344,6 +345,35 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do                 %{"name" => "link", "value" => "cofe.io"}               ] +      fields = +        [ +          "fields_attributes[1][name]=link", +          "fields_attributes[1][value]=cofe.io", +          "fields_attributes[0][name]=<a href=\"http://google.com\">foo</a>", +          "fields_attributes[0][value]=bar" +        ] +        |> Enum.join("&") + +      account = +        conn +        |> put_req_header("content-type", "application/x-www-form-urlencoded") +        |> assign(:user, user) +        |> patch("/api/v1/accounts/update_credentials", fields) +        |> json_response(200) + +      assert account["fields"] == [ +               %{"name" => "foo", "value" => "bar"}, +               %{"name" => "link", "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)} +             ] + +      assert account["source"]["fields"] == [ +               %{ +                 "name" => "<a href=\"http://google.com\">foo</a>", +                 "value" => "bar" +               }, +               %{"name" => "link", "value" => "cofe.io"} +             ] +        name_limit = Pleroma.Config.get([:instance, :account_field_name_length])        value_limit = Pleroma.Config.get([:instance, :account_field_value_length]) @@ -354,7 +384,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert %{"error" => "Invalid request"} ==                 conn                 |> assign(:user, user) -               |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +               |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403)        long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join() @@ -364,7 +394,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert %{"error" => "Invalid request"} ==                 conn                 |> assign(:user, user) -               |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +               |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403)        Pleroma.Config.put([:instance, :max_account_fields], 1) @@ -377,8 +407,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert %{"error" => "Invalid request"} ==                 conn                 |> assign(:user, user) -               |> patch("/api/v1/accounts/update_credentials", %{"fields" => fields}) +               |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})                 |> json_response(403) + +      fields = [ +        %{"name" => "foo", "value" => ""}, +        %{"name" => "", "value" => "bar"} +      ] + +      account = +        conn +        |> assign(:user, user) +        |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) +        |> json_response(200) + +      assert account["fields"] == [ +               %{"name" => "foo", "value" => ""} +             ]      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 8c8017838..6a59c3d94 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -849,4 +849,34 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        assert [] = json_response(conn, 200)      end    end + +  test "getting a list of mutes", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, user} = User.mute(user, other_user) + +    conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/mutes") + +    other_user_id = to_string(other_user.id) +    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) +  end + +  test "getting a list of blocks", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, user} = User.block(user, other_user) + +    conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/blocks") + +    other_user_id = to_string(other_user.id) +    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) +  end  end diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs index 7117fc76a..a308a7620 100644 --- a/test/web/mastodon_api/controllers/conversation_controller_test.exs +++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs @@ -10,19 +10,23 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do    import Pleroma.Factory -  test "Conversations", %{conn: conn} do +  test "returns a list of conversations", %{conn: conn} do      user_one = insert(:user)      user_two = insert(:user)      user_three = insert(:user)      {:ok, user_two} = User.follow(user_two, user_one) +    assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0 +      {:ok, direct} =        CommonAPI.post(user_one, %{          "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",          "visibility" => "direct"        }) +    assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 1 +      {:ok, _follower_only} =        CommonAPI.post(user_one, %{          "status" => "Hi @#{user_two.nickname}!", @@ -52,23 +56,100 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do      assert is_binary(res_id)      assert unread == true      assert res_last_status["id"] == direct.id +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 +  end -    # Apparently undocumented API endpoint -    res_conn = +  test "updates the last_status on reply", %{conn: conn} do +    user_one = insert(:user) +    user_two = insert(:user) + +    {:ok, direct} = +      CommonAPI.post(user_one, %{ +        "status" => "Hi @#{user_two.nickname}", +        "visibility" => "direct" +      }) + +    {:ok, direct_reply} = +      CommonAPI.post(user_two, %{ +        "status" => "reply", +        "visibility" => "direct", +        "in_reply_to_status_id" => direct.id +      }) + +    [%{"last_status" => res_last_status}] =        conn        |> assign(:user, user_one) -      |> post("/api/v1/conversations/#{res_id}/read") +      |> get("/api/v1/conversations") +      |> json_response(200) -    assert response = json_response(res_conn, 200) -    assert length(response["accounts"]) == 2 -    assert response["last_status"]["id"] == direct.id -    assert response["unread"] == false +    assert res_last_status["id"] == direct_reply.id +  end + +  test "the user marks a conversation as read", %{conn: conn} do +    user_one = insert(:user) +    user_two = insert(:user) + +    {:ok, direct} = +      CommonAPI.post(user_one, %{ +        "status" => "Hi @#{user_two.nickname}", +        "visibility" => "direct" +      }) + +    [%{"id" => direct_conversation_id, "unread" => true}] = +      conn +      |> assign(:user, user_one) +      |> get("/api/v1/conversations") +      |> json_response(200) + +    %{"unread" => false} = +      conn +      |> assign(:user, user_one) +      |> post("/api/v1/conversations/#{direct_conversation_id}/read") +      |> json_response(200) + +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0 + +    # The conversation is marked as unread on reply +    {:ok, _} = +      CommonAPI.post(user_two, %{ +        "status" => "reply", +        "visibility" => "direct", +        "in_reply_to_status_id" => direct.id +      }) + +    [%{"unread" => true}] = +      conn +      |> assign(:user, user_one) +      |> get("/api/v1/conversations") +      |> json_response(200) + +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 + +    # A reply doesn't increment the user's unread_conversation_count if the conversation is unread +    {:ok, _} = +      CommonAPI.post(user_two, %{ +        "status" => "reply", +        "visibility" => "direct", +        "in_reply_to_status_id" => direct.id +      }) + +    assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 +  end + +  test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do +    user_one = insert(:user) +    user_two = insert(:user) + +    {:ok, direct} = +      CommonAPI.post(user_one, %{ +        "status" => "Hi @#{user_two.nickname}!", +        "visibility" => "direct" +      }) -    # (vanilla) Mastodon frontend behaviour      res_conn =        conn        |> assign(:user, user_one) -      |> get("/api/v1/statuses/#{res_last_status["id"]}/context") +      |> get("/api/v1/statuses/#{direct.id}/context")      assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)    end diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index b648ad6ff..a4bbfe055 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -1242,4 +1242,51 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do               "descendants" => [%{"id" => ^id4}, %{"id" => ^id5}]             } = response    end + +  test "returns the favorites of a user", %{conn: conn} do +    user = insert(:user) +    other_user = insert(:user) + +    {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"}) +    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) + +    {:ok, _, _} = CommonAPI.favorite(activity.id, user) + +    first_conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/favourites") + +    assert [status] = json_response(first_conn, 200) +    assert status["id"] == to_string(activity.id) + +    assert [{"link", _link_header}] = +             Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end) + +    # Honours query params +    {:ok, second_activity} = +      CommonAPI.post(other_user, %{ +        "status" => +          "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." +      }) + +    {:ok, _, _} = CommonAPI.favorite(second_activity.id, user) + +    last_like = status["id"] + +    second_conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/favourites?since_id=#{last_like}") + +    assert [second_status] = json_response(second_conn, 200) +    assert second_status["id"] == to_string(second_activity.id) + +    third_conn = +      conn +      |> assign(:user, user) +      |> get("/api/v1/favourites?limit=0") + +    assert [] = json_response(third_conn, 200) +  end  end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index c03003dac..42a8779c0 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -7,7 +7,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do    alias Pleroma.Notification    alias Pleroma.Repo -  alias Pleroma.User    alias Pleroma.Web.CommonAPI    import Pleroma.Factory @@ -20,36 +19,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do    clear_config([:rich_media, :enabled]) -  test "getting a list of mutes", %{conn: conn} do -    user = insert(:user) -    other_user = insert(:user) - -    {:ok, user} = User.mute(user, other_user) - -    conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/mutes") - -    other_user_id = to_string(other_user.id) -    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) -  end - -  test "getting a list of blocks", %{conn: conn} do -    user = insert(:user) -    other_user = insert(:user) - -    {:ok, user} = User.block(user, other_user) - -    conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/blocks") - -    other_user_id = to_string(other_user.id) -    assert [%{"id" => ^other_user_id}] = json_response(conn, 200) -  end -    test "unimplemented follow_requests, blocks, domain blocks" do      user = insert(:user) @@ -64,53 +33,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do      end)    end -  test "returns the favorites of a user", %{conn: conn} do -    user = insert(:user) -    other_user = insert(:user) - -    {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"}) -    {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) - -    {:ok, _, _} = CommonAPI.favorite(activity.id, user) - -    first_conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/favourites") - -    assert [status] = json_response(first_conn, 200) -    assert status["id"] == to_string(activity.id) - -    assert [{"link", _link_header}] = -             Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end) - -    # Honours query params -    {:ok, second_activity} = -      CommonAPI.post(other_user, %{ -        "status" => -          "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." -      }) - -    {:ok, _, _} = CommonAPI.favorite(second_activity.id, user) - -    last_like = status["id"] - -    second_conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/favourites?since_id=#{last_like}") - -    assert [second_status] = json_response(second_conn, 200) -    assert second_status["id"] == to_string(second_activity.id) - -    third_conn = -      conn -      |> assign(:user, user) -      |> get("/api/v1/favourites?limit=0") - -    assert [] = json_response(third_conn, 200) -  end -    describe "link headers" do      test "preserves parameters in link headers", %{conn: conn} do        user = insert(:user) diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 62b2ab7e3..b7a4938a6 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -418,6 +418,27 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do                 following_count: 1               } = AccountView.render("show.json", %{user: user, for: user})      end + +    test "shows unread_conversation_count only to the account owner" do +      user = insert(:user) +      other_user = insert(:user) + +      {:ok, _activity} = +        CommonAPI.post(user, %{ +          "status" => "Hey @#{other_user.nickname}.", +          "visibility" => "direct" +        }) + +      user = User.get_cached_by_ap_id(user.ap_id) + +      assert AccountView.render("show.json", %{user: user, for: other_user})[:pleroma][ +               :unread_conversation_count +             ] == nil + +      assert AccountView.render("show.json", %{user: user, for: user})[:pleroma][ +               :unread_conversation_count +             ] == 1 +    end    end    describe "follow requests counter" do diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index 81ab82e2b..c9043a69a 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -100,5 +100,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do        NotificationView.render("index.json", %{notifications: [notification], for: followed})      assert [expected] == result + +    User.perform(:delete, follower) +    notification = Notification |> Repo.one() |> Repo.preload(:activity) + +    assert [] == +             NotificationView.render("index.json", %{notifications: [notification], for: followed})    end  end diff --git a/test/web/metadata/feed_test.exs b/test/web/metadata/feed_test.exs new file mode 100644 index 000000000..50e9ce52e --- /dev/null +++ b/test/web/metadata/feed_test.exs @@ -0,0 +1,18 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Metadata.Providers.FeedTest do +  use Pleroma.DataCase +  import Pleroma.Factory +  alias Pleroma.Web.Metadata.Providers.Feed + +  test "it renders a link to user's atom feed" do +    user = insert(:user, nickname: "lain") + +    assert Feed.build_tags(%{user: user}) == [ +             {:link, +              [rel: "alternate", type: "application/atom+xml", href: "/users/lain/feed.atom"], []} +           ] +  end +end diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index 4d0741d14..41aaf6189 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -557,7 +557,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do              "password" => "test",              "client_id" => app.client_id,              "redirect_uri" => redirect_uri, -            "scope" => "read write", +            "scope" => "read:subscope write",              "state" => "statepassed"            }          }) @@ -570,7 +570,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        assert %{"state" => "statepassed", "code" => code} = query        auth = Repo.get_by(Authorization, token: code)        assert auth -      assert auth.scopes == ["read", "write"] +      assert auth.scopes == ["read:subscope", "write"]      end      test "returns 401 for wrong credentials", %{conn: conn} do @@ -627,7 +627,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        assert result =~ "This action is outside the authorized scopes"      end -    test "returns 401 for scopes beyond app scopes", %{conn: conn} do +    test "returns 401 for scopes beyond app scopes hierarchy", %{conn: conn} do        user = insert(:user)        app = insert(:oauth_app, scopes: ["read", "write"])        redirect_uri = OAuthController.default_redirect_uri(app) diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index f06023dff..b1af918d8 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -72,28 +72,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do      end    end -  test "gets a feed", %{conn: conn} do -    note_activity = insert(:note_activity) -    object = Object.normalize(note_activity) -    user = User.get_cached_by_ap_id(note_activity.data["actor"]) - -    conn = -      conn -      |> put_req_header("content-type", "application/atom+xml") -      |> get("/users/#{user.nickname}/feed.atom") - -    assert response(conn, 200) =~ object.data["content"] -  end - -  test "returns 404 for a missing feed", %{conn: conn} do -    conn = -      conn -      |> put_req_header("content-type", "application/atom+xml") -      |> get("/users/nonexisting/feed.atom") - -    assert response(conn, 404) -  end -    describe "GET object/2" do      test "gets an object", %{conn: conn} do        note_activity = insert(:note_activity) @@ -355,185 +333,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do      end    end -  describe "feed_redirect" do -    test "undefined format. it redirects to feed", %{conn: conn} do -      note_activity = insert(:note_activity) -      user = User.get_cached_by_ap_id(note_activity.data["actor"]) - -      response = -        conn -        |> put_req_header("accept", "application/xml") -        |> get("/users/#{user.nickname}") -        |> response(302) - -      assert response == -               "<html><body>You are being <a href=\"#{Pleroma.Web.base_url()}/users/#{ -                 user.nickname -               }/feed.atom\">redirected</a>.</body></html>" -    end - -    test "undefined format. it returns error when user not found", %{conn: conn} do -      response = -        conn -        |> put_req_header("accept", "application/xml") -        |> get("/users/jimm") -        |> response(404) - -      assert response == ~S({"error":"Not found"}) -    end - -    test "activity+json format. it redirects on actual feed of user", %{conn: conn} do -      note_activity = insert(:note_activity) -      user = User.get_cached_by_ap_id(note_activity.data["actor"]) - -      response = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/users/#{user.nickname}") -        |> json_response(200) - -      assert response["endpoints"] == %{ -               "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize", -               "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps", -               "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token", -               "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox", -               "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media" -             } - -      assert response["@context"] == [ -               "https://www.w3.org/ns/activitystreams", -               "http://localhost:4001/schemas/litepub-0.1.jsonld", -               %{"@language" => "und"} -             ] - -      assert Map.take(response, [ -               "followers", -               "following", -               "id", -               "inbox", -               "manuallyApprovesFollowers", -               "name", -               "outbox", -               "preferredUsername", -               "summary", -               "tag", -               "type", -               "url" -             ]) == %{ -               "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers", -               "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following", -               "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}", -               "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox", -               "manuallyApprovesFollowers" => false, -               "name" => user.name, -               "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox", -               "preferredUsername" => user.nickname, -               "summary" => user.bio, -               "tag" => [], -               "type" => "Person", -               "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}" -             } -    end - -    test "activity+json format. it returns error whe use not found", %{conn: conn} do -      response = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get("/users/jimm") -        |> json_response(404) - -      assert response == "Not found" -    end - -    test "json format. it redirects on actual feed of user", %{conn: conn} do -      note_activity = insert(:note_activity) -      user = User.get_cached_by_ap_id(note_activity.data["actor"]) - -      response = -        conn -        |> put_req_header("accept", "application/json") -        |> get("/users/#{user.nickname}") -        |> json_response(200) - -      assert response["endpoints"] == %{ -               "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize", -               "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps", -               "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token", -               "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox", -               "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media" -             } - -      assert response["@context"] == [ -               "https://www.w3.org/ns/activitystreams", -               "http://localhost:4001/schemas/litepub-0.1.jsonld", -               %{"@language" => "und"} -             ] - -      assert Map.take(response, [ -               "followers", -               "following", -               "id", -               "inbox", -               "manuallyApprovesFollowers", -               "name", -               "outbox", -               "preferredUsername", -               "summary", -               "tag", -               "type", -               "url" -             ]) == %{ -               "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers", -               "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following", -               "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}", -               "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox", -               "manuallyApprovesFollowers" => false, -               "name" => user.name, -               "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox", -               "preferredUsername" => user.nickname, -               "summary" => user.bio, -               "tag" => [], -               "type" => "Person", -               "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}" -             } -    end - -    test "json format. it returns error whe use not found", %{conn: conn} do -      response = -        conn -        |> put_req_header("accept", "application/json") -        |> get("/users/jimm") -        |> json_response(404) - -      assert response == "Not found" -    end - -    test "html format. it redirects on actual feed of user", %{conn: conn} do -      note_activity = insert(:note_activity) -      user = User.get_cached_by_ap_id(note_activity.data["actor"]) - -      response = -        conn -        |> get("/users/#{user.nickname}") -        |> response(200) - -      assert response == -               Fallback.RedirectController.redirector_with_meta( -                 conn, -                 %{user: user} -               ).resp_body -    end - -    test "html format. it returns error when user not found", %{conn: conn} do -      response = -        conn -        |> get("/users/jimm") -        |> json_response(404) - -      assert response == %{"error" => "Not found"} -    end -  end -    describe "GET /notice/:id/embed_player" do      test "render embed player", %{conn: conn} do        note_activity = insert(:note_activity) diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs index 7eaeda4a0..8a6528cbb 100644 --- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do    alias Pleroma.Conversation.Participation    alias Pleroma.Notification    alias Pleroma.Repo +  alias Pleroma.User    alias Pleroma.Web.CommonAPI    import Pleroma.Factory @@ -73,6 +74,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do      participation = Repo.preload(participation, :recipients) +    user = User.get_cached_by_id(user.id)      assert [user] == participation.recipients      assert other_user not in participation.recipients diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index b8fcd41fa..d33eb1e42 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -233,30 +233,68 @@ defmodule Pleroma.Web.StreamerTest do      end    end -  test "it doesn't send to blocked users" do -    user = insert(:user) -    blocked_user = insert(:user) -    {:ok, user} = User.block(user, blocked_user) +  describe "blocks" do +    test "it doesn't send messages involving blocked users" do +      user = insert(:user) +      blocked_user = insert(:user) +      {:ok, user} = User.block(user, blocked_user) -    task = -      Task.async(fn -> -        refute_receive {:text, _}, 1_000 -      end) +      task = +        Task.async(fn -> +          refute_receive {:text, _}, 1_000 +        end) -    fake_socket = %StreamerSocket{ -      transport_pid: task.pid, -      user: user -    } +      fake_socket = %StreamerSocket{ +        transport_pid: task.pid, +        user: user +      } -    {:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"}) +      {:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"}) -    topics = %{ -      "public" => [fake_socket] -    } +      topics = %{ +        "public" => [fake_socket] +      } -    Worker.push_to_socket(topics, "public", activity) +      Worker.push_to_socket(topics, "public", activity) -    Task.await(task) +      Task.await(task) +    end + +    test "it doesn't send messages transitively involving blocked users" do +      blocker = insert(:user) +      blockee = insert(:user) +      friend = insert(:user) + +      task = +        Task.async(fn -> +          refute_receive {:text, _}, 1_000 +        end) + +      fake_socket = %StreamerSocket{ +        transport_pid: task.pid, +        user: blocker +      } + +      topics = %{ +        "public" => [fake_socket] +      } + +      {:ok, blocker} = User.block(blocker, blockee) + +      {:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"}) + +      Worker.push_to_socket(topics, "public", activity_one) + +      {:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"}) + +      Worker.push_to_socket(topics, "public", activity_two) + +      {:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"}) + +      Worker.push_to_socket(topics, "public", activity_three) + +      Task.await(task) +    end    end    test "it doesn't send unwanted DMs to list" do diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index 56e318182..9d4cb70f0 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -81,19 +81,21 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do        assert response == "job started"      end -    test "requires 'follow' permission", %{conn: conn} do +    test "requires 'follow' or 'write:follows' permissions", %{conn: conn} 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] do +      for token <- [token1, token2, token3] do          conn =            conn            |> put_req_header("authorization", "Bearer #{token.token}")            |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"}) -        if token == token1 do -          assert %{"error" => "Insufficient permissions: follow."} == json_response(conn, 403) +        if token == token3 do +          assert %{"error" => "Insufficient permissions: follow | write:follows."} == +                   json_response(conn, 403)          else            assert json_response(conn, 200)          end | 
