diff options
Diffstat (limited to 'test')
26 files changed, 864 insertions, 180 deletions
diff --git a/test/federation/federation_test.exs b/test/federation/federation_test.exs new file mode 100644 index 000000000..45800568a --- /dev/null +++ b/test/federation/federation_test.exs @@ -0,0 +1,47 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Integration.FederationTest do +  use Pleroma.DataCase +  @moduletag :federated +  import Pleroma.Cluster + +  setup_all do +    Pleroma.Cluster.spawn_default_cluster() +    :ok +  end + +  @federated1 :"federated1@127.0.0.1" +  describe "federated cluster primitives" do +    test "within/2 captures local bindings and executes block on remote node" do +      captured_binding = :captured + +      result = +        within @federated1 do +          user = Pleroma.Factory.insert(:user) +          {captured_binding, node(), user} +        end + +      assert {:captured, @federated1, user} = result +      refute Pleroma.User.get_by_id(user.id) +      assert user.id == within(@federated1, do: Pleroma.User.get_by_id(user.id)).id +    end + +    test "runs webserver on customized port" do +      {nickname, url, url_404} = +        within @federated1 do +          import Pleroma.Web.Router.Helpers +          user = Pleroma.Factory.insert(:user) +          user_url = account_url(Pleroma.Web.Endpoint, :show, user) +          url_404 = account_url(Pleroma.Web.Endpoint, :show, "not-exists") + +          {user.nickname, user_url, url_404} +        end + +      assert {:ok, {{_, 200, _}, _headers, body}} = :httpc.request(~c"#{url}") +      assert %{"acct" => ^nickname} = Jason.decode!(body) +      assert {:ok, {{_, 404, _}, _headers, _body}} = :httpc.request(~c"#{url_404}") +    end +  end +end diff --git a/test/fixtures/tesla_mock/admin@mastdon.example.org.json b/test/fixtures/tesla_mock/admin@mastdon.example.org.json index 8159dc20a..9fdd6557c 100644 --- a/test/fixtures/tesla_mock/admin@mastdon.example.org.json +++ b/test/fixtures/tesla_mock/admin@mastdon.example.org.json @@ -9,7 +9,11 @@      "inReplyToAtomUri": "ostatus:inReplyToAtomUri",      "conversation": "ostatus:conversation",      "toot": "http://joinmastodon.org/ns#", -    "Emoji": "toot:Emoji" +    "Emoji": "toot:Emoji", +    "alsoKnownAs": { +      "@id": "as:alsoKnownAs", +      "@type": "@id" +    }    }],    "id": "http://mastodon.example.org/users/admin",    "type": "Person", @@ -50,5 +54,6 @@      "type": "Image",      "mediaType": "image/png",      "url": "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" -  } +  }, +  "alsoKnownAs": ["http://example.org/users/foo"]  } diff --git a/test/fixtures/users_mock/friendica_followers.json b/test/fixtures/users_mock/friendica_followers.json new file mode 100644 index 000000000..7b86b5fe2 --- /dev/null +++ b/test/fixtures/users_mock/friendica_followers.json @@ -0,0 +1,19 @@ +{ +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "vcard": "http://www.w3.org/2006/vcard/ns#", +      "dfrn": "http://purl.org/macgirvin/dfrn/1.0/", +      "diaspora": "https://diasporafoundation.org/ns/", +      "litepub": "http://litepub.social/ns#", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "sensitive": "as:sensitive", +      "Hashtag": "as:Hashtag", +      "directMessage": "litepub:directMessage" +    } +  ], +  "id": "http://localhost:8080/followers/fuser3", +  "type": "OrderedCollection", +  "totalItems": 296 +} diff --git a/test/fixtures/users_mock/friendica_following.json b/test/fixtures/users_mock/friendica_following.json new file mode 100644 index 000000000..7c526befc --- /dev/null +++ b/test/fixtures/users_mock/friendica_following.json @@ -0,0 +1,19 @@ +{ +  "@context": [ +    "https://www.w3.org/ns/activitystreams", +    "https://w3id.org/security/v1", +    { +      "vcard": "http://www.w3.org/2006/vcard/ns#", +      "dfrn": "http://purl.org/macgirvin/dfrn/1.0/", +      "diaspora": "https://diasporafoundation.org/ns/", +      "litepub": "http://litepub.social/ns#", +      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +      "sensitive": "as:sensitive", +      "Hashtag": "as:Hashtag", +      "directMessage": "litepub:directMessage" +    } +  ], +  "id": "http://localhost:8080/following/fuser3", +  "type": "OrderedCollection", +  "totalItems": 32 +} diff --git a/test/following_relationship_test.exs b/test/following_relationship_test.exs new file mode 100644 index 000000000..93c079814 --- /dev/null +++ b/test/following_relationship_test.exs @@ -0,0 +1,47 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.FollowingRelationshipTest do +  use Pleroma.DataCase + +  alias Pleroma.FollowingRelationship +  alias Pleroma.Web.ActivityPub.InternalFetchActor +  alias Pleroma.Web.ActivityPub.Relay + +  import Pleroma.Factory + +  describe "following/1" do +    test "returns following addresses without internal.fetch" do +      user = insert(:user) +      fetch_actor = InternalFetchActor.get_actor() +      FollowingRelationship.follow(fetch_actor, user, "accept") +      assert FollowingRelationship.following(fetch_actor) == [user.follower_address] +    end + +    test "returns following addresses without relay" do +      user = insert(:user) +      relay_actor = Relay.get_actor() +      FollowingRelationship.follow(relay_actor, user, "accept") +      assert FollowingRelationship.following(relay_actor) == [user.follower_address] +    end + +    test "returns following addresses without remote user" do +      user = insert(:user) +      actor = insert(:user, local: false) +      FollowingRelationship.follow(actor, user, "accept") +      assert FollowingRelationship.following(actor) == [user.follower_address] +    end + +    test "returns following addresses with local user" do +      user = insert(:user) +      actor = insert(:user, local: true) +      FollowingRelationship.follow(actor, user, "accept") + +      assert FollowingRelationship.following(actor) == [ +               actor.follower_address, +               user.follower_address +             ] +    end +  end +end diff --git a/test/html_test.exs b/test/html_test.exs index f0869534c..c918dbe20 100644 --- a/test/html_test.exs +++ b/test/html_test.exs @@ -228,5 +228,16 @@ defmodule Pleroma.HTMLTest do        assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"      end + +    test "does not crash when there is an HTML entity in a link" do +      user = insert(:user) + +      {:ok, activity} = +        CommonAPI.post(user, %{"status" => "\"http://cofe.com/?boomer=ok&foo=bar\""}) + +      object = Object.normalize(activity) + +      assert {:ok, nil} = HTML.extract_first_external_url(object, object.data["content"]) +    end    end  end diff --git a/test/http/request_builder_test.exs b/test/http/request_builder_test.exs index 170ca916f..80ef25d7b 100644 --- a/test/http/request_builder_test.exs +++ b/test/http/request_builder_test.exs @@ -16,11 +16,21 @@ defmodule Pleroma.HTTP.RequestBuilderTest do      test "send pleroma user agent" do        Pleroma.Config.put([:http, :send_user_agent], true) +      Pleroma.Config.put([:http, :user_agent], :default)        assert RequestBuilder.headers(%{}, []) == %{                 headers: [{"User-Agent", Pleroma.Application.user_agent()}]               }      end + +    test "send custom user agent" do +      Pleroma.Config.put([:http, :send_user_agent], true) +      Pleroma.Config.put([:http, :user_agent], "totally-not-pleroma") + +      assert RequestBuilder.headers(%{}, []) == %{ +               headers: [{"User-Agent", "totally-not-pleroma"}] +             } +    end    end    describe "add_optional_params/3" do diff --git a/test/notification_test.exs b/test/notification_test.exs index f8d429223..dcbffeafe 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -630,6 +630,35 @@ defmodule Pleroma.NotificationTest do        assert Enum.empty?(Notification.for_user(local_user))      end + +    test "move activity generates a notification" do +      %{ap_id: old_ap_id} = old_user = insert(:user) +      %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id]) +      follower = insert(:user) +      other_follower = insert(:user, %{allow_following_move: false}) + +      User.follow(follower, old_user) +      User.follow(other_follower, old_user) + +      Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user) +      ObanHelpers.perform_all() + +      assert [ +               %{ +                 activity: %{ +                   data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id} +                 } +               } +             ] = Notification.for_user(follower) + +      assert [ +               %{ +                 activity: %{ +                   data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id} +                 } +               } +             ] = Notification.for_user(other_follower) +    end    end    describe "for_user" do diff --git a/test/support/cluster.ex b/test/support/cluster.ex new file mode 100644 index 000000000..deb37f361 --- /dev/null +++ b/test/support/cluster.ex @@ -0,0 +1,218 @@ +defmodule Pleroma.Cluster do +  @moduledoc """ +  Facilities for managing a cluster of slave VM's for federated testing. + +  ## Spawning the federated cluster + +  `spawn_cluster/1` spawns a map of slave nodes that are started +  within the running VM. During startup, the slave node is sent all configuration +  from the parent node, as well as all code. After receiving configuration and +  code, the slave then starts all applications currently running on the parent. +  The configuration passed to `spawn_cluster/1` overrides any parent application +  configuration for the provided OTP app and key. This is useful for customizing +  the Ecto database, Phoenix webserver ports, etc. + +  For example, to start a single federated VM named ":federated1", with the +  Pleroma Endpoint running on port 4123, and with a database named +  "pleroma_test1", you would run: + +    endpoint_conf = Application.fetch_env!(:pleroma, Pleroma.Web.Endpoint) +    repo_conf = Application.fetch_env!(:pleroma, Pleroma.Repo) + +    Pleroma.Cluster.spawn_cluster(%{ +      :"federated1@127.0.0.1" => [ +        {:pleroma, Pleroma.Repo, Keyword.merge(repo_conf, database: "pleroma_test1")}, +        {:pleroma, Pleroma.Web.Endpoint, +        Keyword.merge(endpoint_conf, http: [port: 4011], url: [port: 4011], server: true)} +      ] +    }) + +  *Note*: application configuration for a given key is not merged, +  so any customization requires first fetching the existing values +  and merging yourself by providing the merged configuration, +  such as above with the endpoint config and repo config. + +  ## Executing code within a remote node + +  Use the `within/2` macro to execute code within the context of a remote +  federated node. The code block captures all local variable bindings from +  the parent's context and returns the result of the expression after executing +  it on the remote node. For example: + +      import Pleroma.Cluster + +      parent_value = 123 + +      result = +        within :"federated1@127.0.0.1" do +          {node(), parent_value} +        end + +      assert result == {:"federated1@127.0.0.1, 123} + +  *Note*: while local bindings are captured and available within the block, +  other parent contexts like required, aliased, or imported modules are not +  in scope. Those will need to be reimported/aliases/required within the block +  as `within/2` is a remote procedure call. +  """ + +  @extra_apps Pleroma.Mixfile.application()[:extra_applications] + +  @doc """ +  Spawns the default Pleroma federated cluster. + +  Values before may be customized as needed for the test suite. +  """ +  def spawn_default_cluster do +    endpoint_conf = Application.fetch_env!(:pleroma, Pleroma.Web.Endpoint) +    repo_conf = Application.fetch_env!(:pleroma, Pleroma.Repo) + +    spawn_cluster(%{ +      :"federated1@127.0.0.1" => [ +        {:pleroma, Pleroma.Repo, Keyword.merge(repo_conf, database: "pleroma_test_federated1")}, +        {:pleroma, Pleroma.Web.Endpoint, +         Keyword.merge(endpoint_conf, http: [port: 4011], url: [port: 4011], server: true)} +      ], +      :"federated2@127.0.0.1" => [ +        {:pleroma, Pleroma.Repo, Keyword.merge(repo_conf, database: "pleroma_test_federated2")}, +        {:pleroma, Pleroma.Web.Endpoint, +         Keyword.merge(endpoint_conf, http: [port: 4012], url: [port: 4012], server: true)} +      ] +    }) +  end + +  @doc """ +  Spawns a configured map of federated nodes. + +  See `Pleroma.Cluster` module documentation for details. +  """ +  def spawn_cluster(node_configs) do +    # Turn node into a distributed node with the given long name +    :net_kernel.start([:"primary@127.0.0.1"]) + +    # Allow spawned nodes to fetch all code from this node +    {:ok, _} = :erl_boot_server.start([]) +    allow_boot("127.0.0.1") + +    silence_logger_warnings(fn -> +      node_configs +      |> Enum.map(&Task.async(fn -> start_slave(&1) end)) +      |> Enum.map(&Task.await(&1, 60_000)) +    end) +  end + +  @doc """ +  Executes block of code again remote node. + +  See `Pleroma.Cluster` module documentation for details. +  """ +  defmacro within(node, do: block) do +    quote do +      rpc(unquote(node), unquote(__MODULE__), :eval_quoted, [ +        unquote(Macro.escape(block)), +        binding() +      ]) +    end +  end + +  @doc false +  def eval_quoted(block, binding) do +    {result, _binding} = Code.eval_quoted(block, binding, __ENV__) +    result +  end + +  defp start_slave({node_host, override_configs}) do +    log(node_host, "booting federated VM") +    {:ok, node} = :slave.start(~c"127.0.0.1", node_name(node_host), vm_args()) +    add_code_paths(node) +    load_apps_and_transfer_configuration(node, override_configs) +    ensure_apps_started(node) +    {:ok, node} +  end + +  def rpc(node, module, function, args) do +    :rpc.block_call(node, module, function, args) +  end + +  defp vm_args do +    ~c"-loader inet -hosts 127.0.0.1 -setcookie #{:erlang.get_cookie()}" +  end + +  defp allow_boot(host) do +    {:ok, ipv4} = :inet.parse_ipv4_address(~c"#{host}") +    :ok = :erl_boot_server.add_slave(ipv4) +  end + +  defp add_code_paths(node) do +    rpc(node, :code, :add_paths, [:code.get_path()]) +  end + +  defp load_apps_and_transfer_configuration(node, override_configs) do +    Enum.each(Application.loaded_applications(), fn {app_name, _, _} -> +      app_name +      |> Application.get_all_env() +      |> Enum.each(fn {key, primary_config} -> +        rpc(node, Application, :put_env, [app_name, key, primary_config, [persistent: true]]) +      end) +    end) + +    Enum.each(override_configs, fn {app_name, key, val} -> +      rpc(node, Application, :put_env, [app_name, key, val, [persistent: true]]) +    end) +  end + +  defp log(node, msg), do: IO.puts("[#{node}] #{msg}") + +  defp ensure_apps_started(node) do +    loaded_names = Enum.map(Application.loaded_applications(), fn {name, _, _} -> name end) +    app_names = @extra_apps ++ (loaded_names -- @extra_apps) + +    rpc(node, Application, :ensure_all_started, [:mix]) +    rpc(node, Mix, :env, [Mix.env()]) +    rpc(node, __MODULE__, :prepare_database, []) + +    log(node, "starting application") + +    Enum.reduce(app_names, MapSet.new(), fn app, loaded -> +      if Enum.member?(loaded, app) do +        loaded +      else +        {:ok, started} = rpc(node, Application, :ensure_all_started, [app]) +        MapSet.union(loaded, MapSet.new(started)) +      end +    end) +  end + +  @doc false +  def prepare_database do +    log(node(), "preparing database") +    repo_config = Application.get_env(:pleroma, Pleroma.Repo) +    repo_config[:adapter].storage_down(repo_config) +    repo_config[:adapter].storage_up(repo_config) + +    {:ok, _, _} = +      Ecto.Migrator.with_repo(Pleroma.Repo, fn repo -> +        Ecto.Migrator.run(repo, :up, log: false, all: true) +      end) + +    Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual) +    {:ok, _} = Application.ensure_all_started(:ex_machina) +  end + +  defp silence_logger_warnings(func) do +    prev_level = Logger.level() +    Logger.configure(level: :error) +    res = func.() +    Logger.configure(level: prev_level) + +    res +  end + +  defp node_name(node_host) do +    node_host +    |> to_string() +    |> String.split("@") +    |> Enum.at(0) +    |> String.to_atom() +  end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index e3f797f64..bb8a64e72 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -31,7 +31,6 @@ defmodule Pleroma.Factory do        nickname: sequence(:nickname, &"nick#{&1}"),        password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),        bio: sequence(:bio, &"Tester Number #{&1}"), -      info: %{},        last_digest_emailed_at: NaiveDateTime.utc_now()      } diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 965335e96..e3a621f49 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1035,6 +1035,22 @@ defmodule HttpRequestMock do       }}    end +  def get("http://localhost:8080/followers/fuser3", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 200, +       body: File.read!("test/fixtures/users_mock/friendica_followers.json") +     }} +  end + +  def get("http://localhost:8080/following/fuser3", _, _, _) do +    {:ok, +     %Tesla.Env{ +       status: 200, +       body: File.read!("test/fixtures/users_mock/friendica_following.json") +     }} +  end +    def get("http://localhost:4001/users/fuser2/followers", _, _, _) do      {:ok,       %Tesla.Env{ diff --git a/test/test_helper.exs b/test/test_helper.exs index c8dbee010..241ad1f94 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -3,7 +3,8 @@  # SPDX-License-Identifier: AGPL-3.0-only  os_exclude = if :os.type() == {:unix, :darwin}, do: [skip_on_mac: true], else: [] -ExUnit.start(exclude: os_exclude) +ExUnit.start(exclude: [:federated | os_exclude]) +  Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual)  Mox.defmock(Pleroma.ReverseProxy.ClientMock, for: Pleroma.ReverseProxy.Client)  {:ok, _} = Application.ensure_all_started(:ex_machina) diff --git a/test/user_search_test.exs b/test/user_search_test.exs index 721af1e5b..98841dbbd 100644 --- a/test/user_search_test.exs +++ b/test/user_search_test.exs @@ -15,6 +15,14 @@ defmodule Pleroma.UserSearchTest do    end    describe "User.search" do +    test "excluded invisible users from results" do +      user = insert(:user, %{nickname: "john t1000"}) +      insert(:user, %{invisible: true, nickname: "john t800"}) + +      [found_user] = User.search("john") +      assert found_user.id == user.id +    end +      test "accepts limit parameter" do        Enum.each(0..4, &insert(:user, %{nickname: "john#{&1}"}))        assert length(User.search("john", limit: 3)) == 3 diff --git a/test/user_test.exs b/test/user_test.exs index 8fdb6b25f..c345e43e9 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -25,6 +25,25 @@ defmodule Pleroma.UserTest do    clear_config([:instance, :account_activation_required]) +  describe "service actors" do +    test "returns invisible actor" do +      uri = "#{Pleroma.Web.Endpoint.url()}/internal/fetch-test" +      followers_uri = "#{uri}/followers" +      user = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test") + +      assert %User{ +               nickname: "internal.fetch-test", +               invisible: true, +               local: true, +               ap_id: ^uri, +               follower_address: ^followers_uri +             } = user + +      user2 = User.get_or_create_service_actor_by_ap_id(uri, "internal.fetch-test") +      assert user.id == user2.id +    end +  end +    describe "when tags are nil" do      test "tagging a user" do        user = insert(:user, %{tags: nil}) @@ -148,9 +167,10 @@ defmodule Pleroma.UserTest do      {:ok, user} = User.follow(user, followed)      user = User.get_cached_by_id(user.id) -      followed = User.get_cached_by_ap_id(followed.ap_id) +      assert followed.follower_count == 1 +    assert user.following_count == 1      assert User.ap_followers(followed) in User.following(user)    end @@ -347,18 +367,6 @@ defmodule Pleroma.UserTest do        assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"      end - -    test "it ensures info is not nil" do -      changeset = User.register_changeset(%User{}, @full_user_data) - -      assert changeset.valid? - -      {:ok, user} = -        changeset -        |> Repo.insert() - -      refute is_nil(user.info) -    end    end    describe "user registration, with :account_activation_required" do @@ -412,8 +420,7 @@ defmodule Pleroma.UserTest do            :user,            local: false,            nickname: "admin@mastodon.example.org", -          ap_id: ap_id, -          info: %{} +          ap_id: ap_id          )        {:ok, fetched_user} = User.get_or_fetch(ap_id) @@ -474,8 +481,7 @@ defmodule Pleroma.UserTest do            local: false,            nickname: "admin@mastodon.example.org",            ap_id: "http://mastodon.example.org/users/admin", -          last_refreshed_at: a_week_ago, -          info: %{} +          last_refreshed_at: a_week_ago          )        assert orig_user.last_refreshed_at == a_week_ago @@ -516,7 +522,6 @@ defmodule Pleroma.UserTest do        name: "Someone",        nickname: "a@b.de",        ap_id: "http...", -      info: %{some: "info"},        avatar: %{some: "avatar"}      } @@ -941,9 +946,9 @@ defmodule Pleroma.UserTest do        {:ok, user} = User.follow(user, user2)        {:ok, _user} = User.deactivate(user) -      info = User.get_cached_user_info(user2) +      user2 = User.get_cached_by_id(user2.id) -      assert info.follower_count == 0 +      assert user2.follower_count == 0        assert [] = User.get_followers(user2)      end @@ -952,13 +957,15 @@ defmodule Pleroma.UserTest do        user2 = insert(:user)        {:ok, user2} = User.follow(user2, user) +      assert user2.following_count == 1        assert User.following_count(user2) == 1        {:ok, _user} = User.deactivate(user) -      info = User.get_cached_user_info(user2) +      user2 = User.get_cached_by_id(user2.id) -      assert info.following_count == 0 +      assert refresh_record(user2).following_count == 0 +      assert user2.following_count == 0        assert User.following_count(user2) == 0        assert [] = User.get_friends(user2)      end @@ -1121,8 +1128,7 @@ defmodule Pleroma.UserTest do          ap_id: user.ap_id,          name: user.name,          nickname: user.nickname, -        bio: String.duplicate("h", current_max_length + 1), -        info: %{} +        bio: String.duplicate("h", current_max_length + 1)        }        assert {:ok, %User{}} = User.insert_or_update_user(data) @@ -1135,8 +1141,7 @@ defmodule Pleroma.UserTest do        data = %{          ap_id: user.ap_id,          name: String.duplicate("h", current_max_length + 1), -        nickname: user.nickname, -        info: %{} +        nickname: user.nickname        }        assert {:ok, %User{}} = User.insert_or_update_user(data) @@ -1160,13 +1165,12 @@ defmodule Pleroma.UserTest do    describe "caching" do      test "invalidate_cache works" do        user = insert(:user) -      _user_info = User.get_cached_user_info(user) +      User.set_cache(user)        User.invalidate_cache(user)        {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")        {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}") -      {:ok, nil} = Cachex.get(:user_cache, "user_info:#{user.id}")      end      test "User.delete() plugs any possible zombie objects" do @@ -1322,7 +1326,7 @@ defmodule Pleroma.UserTest do      {:ok, user} = User.block(user, follower) -    assert User.user_info(user).follower_count == 2 +    assert user.follower_count == 2    end    describe "list_inactive_users_query/1" do @@ -1499,51 +1503,6 @@ defmodule Pleroma.UserTest do      end    end -  describe "set_info_cache/2" do -    setup do -      user = insert(:user) -      {:ok, user: user} -    end - -    test "update from args", %{user: user} do -      User.set_info_cache(user, %{following_count: 15, follower_count: 18}) - -      %{follower_count: followers, following_count: following} = User.get_cached_user_info(user) -      assert followers == 18 -      assert following == 15 -    end - -    test "without args", %{user: user} do -      User.set_info_cache(user, %{}) - -      %{follower_count: followers, following_count: following} = User.get_cached_user_info(user) -      assert followers == 0 -      assert following == 0 -    end -  end - -  describe "user_info/2" do -    setup do -      user = insert(:user) -      {:ok, user: user} -    end - -    test "update from args", %{user: user} do -      %{follower_count: followers, following_count: following} = -        User.user_info(user, %{following_count: 15, follower_count: 18}) - -      assert followers == 18 -      assert following == 15 -    end - -    test "without args", %{user: user} do -      %{follower_count: followers, following_count: following} = User.user_info(user) - -      assert followers == 0 -      assert following == 0 -    end -  end -    describe "is_internal_user?/1" do      test "non-internal user returns false" do        user = insert(:user) @@ -1600,14 +1559,14 @@ defmodule Pleroma.UserTest do            ap_enabled: true          ) -      assert User.user_info(other_user).following_count == 0 -      assert User.user_info(other_user).follower_count == 0 +      assert other_user.following_count == 0 +      assert other_user.follower_count == 0        {:ok, user} = Pleroma.User.follow(user, other_user)        other_user = Pleroma.User.get_by_id(other_user.id) -      assert User.user_info(user).following_count == 1 -      assert User.user_info(other_user).follower_count == 1 +      assert user.following_count == 1 +      assert other_user.follower_count == 1      end      test "syncronizes the counters with the remote instance for the followed when enabled" do @@ -1623,14 +1582,14 @@ defmodule Pleroma.UserTest do            ap_enabled: true          ) -      assert User.user_info(other_user).following_count == 0 -      assert User.user_info(other_user).follower_count == 0 +      assert other_user.following_count == 0 +      assert other_user.follower_count == 0        Pleroma.Config.put([:instance, :external_user_synchronization], true)        {:ok, _user} = User.follow(user, other_user)        other_user = User.get_by_id(other_user.id) -      assert User.user_info(other_user).follower_count == 437 +      assert other_user.follower_count == 437      end      test "syncronizes the counters with the remote instance for the follower when enabled" do @@ -1646,13 +1605,13 @@ defmodule Pleroma.UserTest do            ap_enabled: true          ) -      assert User.user_info(other_user).following_count == 0 -      assert User.user_info(other_user).follower_count == 0 +      assert other_user.following_count == 0 +      assert other_user.follower_count == 0        Pleroma.Config.put([:instance, :external_user_synchronization], true)        {:ok, other_user} = User.follow(other_user, user) -      assert User.user_info(other_user).following_count == 152 +      assert other_user.following_count == 152      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 a5414c521..1aa73d75c 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -110,6 +110,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert json_response(conn, 200) == UserView.render("user.json", %{user: user})      end + +    test "it returns 404 for remote users", %{ +      conn: conn +    } do +      user = insert(:user, local: false, nickname: "remoteuser@example.com") + +      conn = +        conn +        |> put_req_header("accept", "application/json") +        |> get("/users/#{user.nickname}.json") + +      assert json_response(conn, 404) +    end    end    describe "/object/:uuid" do diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index d437ad456..2677b9e36 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -4,8 +4,11 @@  defmodule Pleroma.Web.ActivityPub.ActivityPubTest do    use Pleroma.DataCase +  use Oban.Testing, repo: Pleroma.Repo +    alias Pleroma.Activity    alias Pleroma.Builders.ActivityBuilder +  alias Pleroma.Notification    alias Pleroma.Object    alias Pleroma.User    alias Pleroma.Web.ActivityPub.ActivityPub @@ -1554,5 +1557,80 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert follow_info.hide_followers == false        assert follow_info.hide_follows == true      end + +    test "detects hidden follows/followers for friendica" do +      user = +        insert(:user, +          local: false, +          follower_address: "http://localhost:8080/followers/fuser3", +          following_address: "http://localhost:8080/following/fuser3" +        ) + +      {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user) +      assert follow_info.hide_followers == true +      assert follow_info.follower_count == 296 +      assert follow_info.following_count == 32 +      assert follow_info.hide_follows == true +    end +  end + +  describe "Move activity" do +    test "create" do +      %{ap_id: old_ap_id} = old_user = insert(:user) +      %{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id]) +      follower = insert(:user) +      follower_move_opted_out = insert(:user, allow_following_move: false) + +      User.follow(follower, old_user) +      User.follow(follower_move_opted_out, old_user) + +      assert User.following?(follower, old_user) +      assert User.following?(follower_move_opted_out, old_user) + +      assert {:ok, activity} = ActivityPub.move(old_user, new_user) + +      assert %Activity{ +               actor: ^old_ap_id, +               data: %{ +                 "actor" => ^old_ap_id, +                 "object" => ^old_ap_id, +                 "target" => ^new_ap_id, +                 "type" => "Move" +               }, +               local: true +             } = activity + +      params = %{ +        "op" => "move_following", +        "origin_id" => old_user.id, +        "target_id" => new_user.id +      } + +      assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params) + +      Pleroma.Workers.BackgroundWorker.perform(params, nil) + +      refute User.following?(follower, old_user) +      assert User.following?(follower, new_user) + +      assert User.following?(follower_move_opted_out, old_user) +      refute User.following?(follower_move_opted_out, new_user) + +      activity = %Activity{activity | object: nil} + +      assert [%Notification{activity: ^activity}] = +               Notification.for_user_since(follower, ~N[2019-04-13 11:22:33]) + +      assert [%Notification{activity: ^activity}] = +               Notification.for_user_since(follower_move_opted_out, ~N[2019-04-13 11:22:33]) +    end + +    test "old user must be in the new user's `also_known_as` list" do +      old_user = insert(:user) +      new_user = insert(:user) + +      assert {:error, "Target account must have the origin in `alsoKnownAs`"} = +               ActivityPub.move(old_user, new_user) +    end    end  end diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 0bdd514e9..5da358c43 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -39,6 +39,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert activity == returned_activity      end +    @tag capture_log: true      test "it fetches replied-to activities if we don't have them" do        data =          File.read!("test/fixtures/mastodon-post-activity.json") @@ -533,6 +534,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert object.data["content"] == "this is a private toot"      end +    @tag capture_log: true      test "it rejects incoming announces with an inlined activity from another origin" do        data =          File.read!("test/fixtures/bogus-mastodon-announce.json") @@ -681,6 +683,37 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert user.bio == "<p>Some bio</p>"      end +    test "it works with alsoKnownAs" do +      {:ok, %Activity{data: %{"actor" => actor}}} = +        "test/fixtures/mastodon-post-activity.json" +        |> File.read!() +        |> Poison.decode!() +        |> Transmogrifier.handle_incoming() + +      assert User.get_cached_by_ap_id(actor).also_known_as == ["http://example.org/users/foo"] + +      {:ok, _activity} = +        "test/fixtures/mastodon-update.json" +        |> File.read!() +        |> Poison.decode!() +        |> Map.put("actor", actor) +        |> Map.update!("object", fn object -> +          object +          |> Map.put("actor", actor) +          |> Map.put("id", actor) +          |> Map.put("alsoKnownAs", [ +            "http://mastodon.example.org/users/foo", +            "http://example.org/users/bar" +          ]) +        end) +        |> Transmogrifier.handle_incoming() + +      assert User.get_cached_by_ap_id(actor).also_known_as == [ +               "http://mastodon.example.org/users/foo", +               "http://example.org/users/bar" +             ] +    end +      test "it works with custom profile fields" do        {:ok, activity} =          "test/fixtures/mastodon-post-activity.json" @@ -814,6 +847,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert Activity.get_by_id(activity.id)      end +    @tag capture_log: true      test "it works for incoming user deletes" do        %{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin") @@ -1269,6 +1303,30 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]        assert [user.follower_address] == activity.data["to"]      end + +    test "it accepts Move activities" do +      old_user = insert(:user) +      new_user = insert(:user) + +      message = %{ +        "@context" => "https://www.w3.org/ns/activitystreams", +        "type" => "Move", +        "actor" => old_user.ap_id, +        "object" => old_user.ap_id, +        "target" => new_user.ap_id +      } + +      assert :error = Transmogrifier.handle_incoming(message) + +      {:ok, _new_user} = User.update_and_set_cache(new_user, %{also_known_as: [old_user.ap_id]}) + +      assert {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(message) +      assert activity.actor == old_user.ap_id +      assert activity.data["actor"] == old_user.ap_id +      assert activity.data["object"] == old_user.ap_id +      assert activity.data["target"] == new_user.ap_id +      assert activity.data["type"] == "Move" +    end    end    describe "prepare outgoing" do @@ -1749,6 +1807,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert modified_object["inReplyToAtomUri"] == ""      end +    @tag capture_log: true      test "returns modified object when allowed incoming reply", %{data: data} do        object_with_reply =          Map.put( @@ -1868,6 +1927,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do               end) =~ "Unsupported URI scheme"      end +    @tag capture_log: true      test "returns {:ok, %Object{}} for success case" do        assert {:ok, %Object{}} =                 Transmogrifier.get_obj_helper("https://shitposter.club/notice/2827873") diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index fd179e8c2..d0131fd90 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -225,7 +225,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do          "roles" => %{"admin" => false, "moderator" => false},          "tags" => [],          "avatar" => User.avatar_url(user) |> MediaProxy.url(), -        "display_name" => HTML.strip_tags(user.name || user.nickname) +        "display_name" => HTML.strip_tags(user.name || user.nickname), +        "confirmation_pending" => false        }        assert expected == json_response(conn, 200) @@ -634,7 +635,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => true,              "tags" => [],              "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname) +            "display_name" => HTML.strip_tags(admin.name || admin.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => user.deactivated, @@ -644,7 +646,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => false,              "tags" => ["foo", "bar"],              "avatar" => User.avatar_url(user) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user.name || user.nickname) +            "display_name" => HTML.strip_tags(user.name || user.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -685,7 +688,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -709,7 +713,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -733,7 +738,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -757,7 +763,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -781,7 +788,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -805,7 +813,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -824,7 +833,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user2) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user2.name || user2.nickname) +                   "display_name" => HTML.strip_tags(user2.name || user2.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -853,7 +863,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -880,7 +891,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => true,              "tags" => [],              "avatar" => User.avatar_url(user) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user.name || user.nickname) +            "display_name" => HTML.strip_tags(user.name || user.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => admin.deactivated, @@ -890,7 +902,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => true,              "tags" => [],              "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname) +            "display_name" => HTML.strip_tags(admin.name || admin.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => false, @@ -900,7 +913,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "roles" => %{"admin" => true, "moderator" => false},              "tags" => [],              "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname) +            "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -929,7 +943,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => admin.local,              "tags" => [],              "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(admin.name || admin.nickname) +            "display_name" => HTML.strip_tags(admin.name || admin.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => false, @@ -939,7 +954,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => second_admin.local,              "tags" => [],              "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname) +            "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -970,7 +986,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => moderator.local,                     "tags" => [],                     "avatar" => User.avatar_url(moderator) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(moderator.name || moderator.nickname) +                   "display_name" => HTML.strip_tags(moderator.name || moderator.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -994,7 +1011,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => user1.local,              "tags" => ["first"],              "avatar" => User.avatar_url(user1) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user1.name || user1.nickname) +            "display_name" => HTML.strip_tags(user1.name || user1.nickname), +            "confirmation_pending" => false            },            %{              "deactivated" => false, @@ -1004,7 +1022,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do              "local" => user2.local,              "tags" => ["second"],              "avatar" => User.avatar_url(user2) |> MediaProxy.url(), -            "display_name" => HTML.strip_tags(user2.name || user2.nickname) +            "display_name" => HTML.strip_tags(user2.name || user2.nickname), +            "confirmation_pending" => false            }          ]          |> Enum.sort_by(& &1["nickname"]) @@ -1040,7 +1059,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => user.local,                     "tags" => [],                     "avatar" => User.avatar_url(user) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(user.name || user.nickname) +                   "display_name" => HTML.strip_tags(user.name || user.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -1066,7 +1086,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                     "local" => true,                     "tags" => [],                     "avatar" => User.avatar_url(admin) |> MediaProxy.url(), -                   "display_name" => HTML.strip_tags(admin.name || admin.nickname) +                   "display_name" => HTML.strip_tags(admin.name || admin.nickname), +                   "confirmation_pending" => false                   }                 ]               } @@ -1135,7 +1156,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "local" => true,                 "tags" => [],                 "avatar" => User.avatar_url(user) |> MediaProxy.url(), -               "display_name" => HTML.strip_tags(user.name || user.nickname) +               "display_name" => HTML.strip_tags(user.name || user.nickname), +               "confirmation_pending" => false               }      log_entry = Repo.one(ModerationLog) @@ -1902,6 +1924,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do        Pleroma.Config.put([:instance, :dynamic_configuration], true)      end +    @tag capture_log: true      test "create new config setting in db", %{conn: conn} do        conn =          post(conn, "/api/pleroma/admin/config", %{ @@ -2840,6 +2863,105 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do                 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"      end    end + +  describe "instances" do +    test "GET /instances/:instance/statuses" do +      admin = insert(:user, is_admin: true) +      user = insert(:user, local: false, nickname: "archaeme@archae.me") +      user2 = insert(:user, local: false, nickname: "test@test.com") +      insert_pair(:note_activity, user: user) +      insert(:note_activity, user: user2) + +      conn = +        build_conn() +        |> assign(:user, admin) +        |> get("/api/pleroma/admin/instances/archae.me/statuses") + +      response = json_response(conn, 200) + +      assert length(response) == 2 + +      conn = +        build_conn() +        |> assign(:user, admin) +        |> get("/api/pleroma/admin/instances/test.com/statuses") + +      response = json_response(conn, 200) + +      assert length(response) == 1 + +      conn = +        build_conn() +        |> assign(:user, admin) +        |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") + +      response = json_response(conn, 200) + +      assert length(response) == 0 +    end +  end + +  describe "PATCH /confirm_email" do +    setup %{conn: conn} do +      admin = insert(:user, is_admin: true) + +      %{conn: assign(conn, :user, admin), admin: admin} +    end + +    test "it confirms emails of two users", %{admin: admin} do +      [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + +      assert first_user.confirmation_pending == true +      assert second_user.confirmation_pending == true + +      build_conn() +      |> assign(:user, admin) +      |> patch("/api/pleroma/admin/users/confirm_email", %{ +        nicknames: [ +          first_user.nickname, +          second_user.nickname +        ] +      }) + +      assert first_user.confirmation_pending == true +      assert second_user.confirmation_pending == true + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{ +                 second_user.nickname +               }" +    end +  end + +  describe "PATCH /resend_confirmation_email" do +    setup %{conn: conn} do +      admin = insert(:user, is_admin: true) + +      %{conn: assign(conn, :user, admin), admin: admin} +    end + +    test "it resend emails for two users", %{admin: admin} do +      [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + +      build_conn() +      |> assign(:user, admin) +      |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{ +        nicknames: [ +          first_user.nickname, +          second_user.nickname +        ] +      }) + +      log_entry = Repo.one(ModerationLog) + +      assert ModerationLog.get_log_entry_message(log_entry) == +               "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{ +                 second_user.nickname +               }" +    end +  end  end  # Needed for testing 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 519b56d6c..77cfce4fa 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 @@ -103,6 +103,21 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do        assert user["locked"] == true      end +    test "updates the user's allow_following_move", %{conn: conn} do +      user = insert(:user) + +      assert user.allow_following_move == true + +      conn = +        conn +        |> assign(:user, user) +        |> patch("/api/v1/accounts/update_credentials", %{allow_following_move: "false"}) + +      assert refresh_record(user).allow_following_move == false +      assert user = json_response(conn, 200) +      assert user["pleroma"]["allow_following_move"] == false +    end +      test "updates the user's default scope", %{conn: conn} do        user = insert(:user) diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 8fc2d9300..585cb8a9e 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.InternalFetchActor    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.OAuth.Token @@ -118,6 +119,28 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        refute acc_one == acc_two        assert acc_two == acc_three      end + +    test "returns 404 when user is invisible", %{conn: conn} do +      user = insert(:user, %{invisible: true}) + +      resp = +        conn +        |> get("/api/v1/accounts/#{user.nickname}") +        |> json_response(404) + +      assert %{"error" => "Can't find user"} = resp +    end + +    test "returns 404 for internal.fetch actor", %{conn: conn} do +      %User{nickname: "internal.fetch"} = InternalFetchActor.get_actor() + +      resp = +        conn +        |> get("/api/v1/accounts/internal.fetch") +        |> json_response(404) + +      assert %{"error" => "Can't find user"} = resp +    end    end    describe "user timelines" do diff --git a/test/web/mastodon_api/controllers/filter_controller_test.exs b/test/web/mastodon_api/controllers/filter_controller_test.exs index 5d5b56c8e..550689788 100644 --- a/test/web/mastodon_api/controllers/filter_controller_test.exs +++ b/test/web/mastodon_api/controllers/filter_controller_test.exs @@ -3,7 +3,7 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do -  use Pleroma.Web.ConnCase, async: true +  use Pleroma.Web.ConnCase    alias Pleroma.Web.MastodonAPI.FilterView diff --git a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs index 9ad6a4fa7..ae5fee2bc 100644 --- a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs +++ b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs @@ -3,7 +3,7 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do -  use Pleroma.Web.ConnCase, async: true +  use Pleroma.Web.ConnCase    alias Pleroma.Repo    alias Pleroma.ScheduledActivity diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index af88841ed..35aefb7dc 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -102,7 +102,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      privacy = user.default_scope      assert %{ -             pleroma: %{notification_settings: ^notification_settings}, +             pleroma: %{notification_settings: ^notification_settings, allow_following_move: true},               source: %{privacy: ^privacy}             } = AccountView.render("show.json", %{user: user, for: user})    end @@ -350,7 +350,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do        }      } -    assert expected == AccountView.render("show.json", %{user: user, for: other_user}) +    assert expected == +             AccountView.render("show.json", %{user: refresh_record(user), for: other_user})    end    test "returns the settings store if the requesting user is the represented user and it's requested specifically" do @@ -374,6 +375,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do      refute result.display_name == "<marquee> username </marquee>"    end +  test "never display nil user follow counts" do +    user = insert(:user, following_count: 0, follower_count: 0) +    result = AccountView.render("show.json", %{user: user}) + +    assert result.following_count == 0 +    assert result.followers_count == 0 +  end +    describe "hiding follows/following" do      test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do        user = diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index c9043a69a..26e1afc85 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -107,4 +107,31 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do      assert [] ==               NotificationView.render("index.json", %{notifications: [notification], for: followed})    end + +  test "Move notification" do +    %{ap_id: old_ap_id} = old_user = insert(:user) +    %{ap_id: _new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id]) +    follower = insert(:user) + +    User.follow(follower, old_user) +    Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user) +    Pleroma.Tests.ObanHelpers.perform_all() + +    old_user = refresh_record(old_user) +    new_user = refresh_record(new_user) + +    [notification] = Notification.for_user(follower) + +    expected = %{ +      id: to_string(notification.id), +      pleroma: %{is_seen: false}, +      type: "move", +      account: AccountView.render("show.json", %{user: old_user, for: follower}), +      target: AccountView.render("show.json", %{user: new_user, for: follower}), +      created_at: Utils.to_masto_date(notification.inserted_at) +    } + +    assert [expected] == +             NotificationView.render("index.json", %{notifications: [notification], for: follower}) +  end  end diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index 37b7b62f5..50235dfef 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -35,23 +35,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        assert redirected_to(conn) == "/notice/#{note_activity.id}"      end -    test "500s when user not found", %{conn: conn} do -      note_activity = insert(:note_activity) -      object = Object.normalize(note_activity) -      user = User.get_cached_by_ap_id(note_activity.data["actor"]) -      User.invalidate_cache(user) -      Pleroma.Repo.delete(user) -      [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"])) -      url = "/objects/#{uuid}" - -      conn = -        conn -        |> put_req_header("accept", "application/xml") -        |> get(url) - -      assert response(conn, 500) == ~S({"error":"Something went wrong"}) -    end -      test "404s on private objects", %{conn: conn} do        note_activity = insert(:direct_note_activity)        object = Object.normalize(note_activity) @@ -82,21 +65,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        assert redirected_to(conn) == "/notice/#{note_activity.id}"      end -    test "505s when user not found", %{conn: conn} do -      note_activity = insert(:note_activity) -      [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"])) -      user = User.get_cached_by_ap_id(note_activity.data["actor"]) -      User.invalidate_cache(user) -      Pleroma.Repo.delete(user) - -      conn = -        conn -        |> put_req_header("accept", "text/html") -        |> get("/activities/#{uuid}") - -      assert response(conn, 500) == ~S({"error":"Something went wrong"}) -    end -      test "404s on private activities", %{conn: conn} do        note_activity = insert(:direct_note_activity)        [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"])) @@ -127,21 +95,28 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do    end    describe "GET notice/2" do -    test "gets a notice in xml format", %{conn: conn} do +    test "redirects to a proper object URL when json requested and the object is local", %{ +      conn: conn +    } do        note_activity = insert(:note_activity) +      expected_redirect_url = Object.normalize(note_activity).data["id"] -      conn -      |> get("/notice/#{note_activity.id}") -      |> response(200) +      redirect_url = +        conn +        |> put_req_header("accept", "application/activity+json") +        |> get("/notice/#{note_activity.id}") +        |> redirected_to() + +      assert redirect_url == expected_redirect_url      end -    test "gets a notice in AS2 format", %{conn: conn} do -      note_activity = insert(:note_activity) +    test "returns a 404 on remote notice when json requested", %{conn: conn} do +      note_activity = insert(:note_activity, local: false)        conn        |> put_req_header("accept", "application/activity+json")        |> get("/notice/#{note_activity.id}") -      |> json_response(200) +      |> response(404)      end      test "500s when actor not found", %{conn: conn} do @@ -157,32 +132,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        assert response(conn, 500) == ~S({"error":"Something went wrong"})      end -    test "only gets a notice in AS2 format for Create messages", %{conn: conn} do -      note_activity = insert(:note_activity) -      url = "/notice/#{note_activity.id}" - -      conn = -        conn -        |> put_req_header("accept", "application/activity+json") -        |> get(url) - -      assert json_response(conn, 200) - -      user = insert(:user) - -      {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user) -      url = "/notice/#{like_activity.id}" - -      assert like_activity.data["type"] == "Like" - -      conn = -        build_conn() -        |> put_req_header("accept", "application/activity+json") -        |> get(url) - -      assert response(conn, 404) -    end -      test "render html for redirect for html format", %{conn: conn} do        note_activity = insert(:note_activity) diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index 80a7541b2..8265f18dd 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -15,7 +15,7 @@ defmodule Pleroma.Web.StreamerTest do    alias Pleroma.Web.Streamer.StreamerSocket    alias Pleroma.Web.Streamer.Worker -  @moduletag needs_streamer: true +  @moduletag needs_streamer: true, capture_log: true    clear_config_all([:instance, :skip_thread_containment])    describe "user streams" do  | 
