Merge branch 'issue/1348' into 'develop'
authorlain <lain@soykaf.club>
Thu, 21 Nov 2019 13:13:14 +0000 (13:13 +0000)
committerlain <lain@soykaf.club>
Thu, 21 Nov 2019 13:13:14 +0000 (13:13 +0000)
[#1348] excluded invisible actors from gets  /api/v1/accounts/:id

See merge request pleroma/pleroma!1937

lib/pleroma/following_relationship.ex
lib/pleroma/user.ex
lib/pleroma/user/search.ex
lib/pleroma/web/activity_pub/relay.ex
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
priv/repo/migrations/20191104133100_set_visible_service_actors.exs [new file with mode: 0644]
test/following_relationship_test.exs [new file with mode: 0644]
test/user_search_test.exs
test/user_test.exs
test/web/mastodon_api/controllers/account_controller_test.exs

index 2ffac17ee135667774c0cd64f110d6425fc81706..3aff9fb76ba6dee1b1f47734f66028918371911f 100644 (file)
@@ -101,7 +101,7 @@ defmodule Pleroma.FollowingRelationship do
       |> select([r, u], u.follower_address)
       |> Repo.all()
 
-    if not user.local or user.nickname in [nil, "internal.fetch"] do
+    if not user.local or user.invisible do
       following
     else
       [user.follower_address | following]
index 34370be203965b9ac1f26a35269dc125df94a4af..b2c61e921d1fc1e492760851f2b9a8ff449974d4 100644 (file)
@@ -133,6 +133,8 @@ defmodule Pleroma.User do
 
   def visible_for?(user, for_user \\ nil)
 
+  def visible_for?(%User{invisible: true}, _), do: false
+
   def visible_for?(%User{id: user_id}, %User{id: for_id}) when user_id == for_id, do: true
 
   def visible_for?(%User{} = user, for_user) do
@@ -1321,22 +1323,23 @@ defmodule Pleroma.User do
     end
   end
 
-  @doc "Creates an internal service actor by URI if missing.  Optionally takes nickname for addressing."
+  @doc """
+  Creates an internal service actor by URI if missing.
+  Optionally takes nickname for addressing.
+  """
   def get_or_create_service_actor_by_ap_id(uri, nickname \\ nil) do
-    with %User{} = user <- get_cached_by_ap_id(uri) do
-      user
-    else
-      _ ->
-        {:ok, user} =
-          %User{}
-          |> cast(%{}, [:ap_id, :nickname, :local])
-          |> put_change(:ap_id, uri)
-          |> put_change(:nickname, nickname)
-          |> put_change(:local, true)
-          |> put_change(:follower_address, uri <> "/followers")
-          |> Repo.insert()
+    with user when is_nil(user) <- get_cached_by_ap_id(uri) do
+      {:ok, user} =
+        %User{
+          invisible: true,
+          local: true,
+          ap_id: uri,
+          nickname: nickname,
+          follower_address: uri <> "/followers"
+        }
+        |> Repo.insert()
 
-        user
+      user
     end
   end
 
index 09664db76b7393a144c9d54972ba3a884eabb7bf..b1bb9d4da0aa65ad14c14a1fe131f88380ecdc19 100644 (file)
@@ -45,6 +45,7 @@ defmodule Pleroma.User.Search do
     for_user
     |> base_query(following)
     |> filter_blocked_user(for_user)
+    |> filter_invisible_users()
     |> filter_blocked_domains(for_user)
     |> fts_search(query_string)
     |> trigram_rank(query_string)
@@ -98,6 +99,10 @@ defmodule Pleroma.User.Search do
   defp base_query(_user, false), do: User
   defp base_query(user, true), do: User.get_followers_query(user)
 
+  defp filter_invisible_users(query) do
+    from(q in query, where: q.invisible == false)
+  end
+
   defp filter_blocked_user(query, %User{blocks: blocks})
        when length(blocks) > 0 do
     from(q in query, where: not (q.ap_id in ^blocks))
index fc2619680f8e00d96606e7918b1291d65519dbe5..99a804568ccf0830529d55d1c17e916fce146c5f 100644 (file)
@@ -14,7 +14,6 @@ defmodule Pleroma.Web.ActivityPub.Relay do
       relay_ap_id()
       |> User.get_or_create_service_actor_by_ap_id()
 
-    {:ok, actor} = User.set_invisible(actor, true)
     actor
   end
 
index 5b01b964b8a52fb85aa05a60de590df627a9f87a..5f2544640427afb24b91f8fe81e4e587789fd907 100644 (file)
@@ -238,7 +238,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   @doc "GET /api/v1/accounts/:id"
   def show(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do
     with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
-         true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do
+         true <- User.visible_for?(user, for_user) do
       render(conn, "show.json", user: user, for: for_user)
     else
       _e -> render_error(conn, :not_found, "Can't find user")
diff --git a/priv/repo/migrations/20191104133100_set_visible_service_actors.exs b/priv/repo/migrations/20191104133100_set_visible_service_actors.exs
new file mode 100644 (file)
index 0000000..6290709
--- /dev/null
@@ -0,0 +1,22 @@
+defmodule Pleroma.Repo.Migrations.SetVisibleServiceActors do
+  use Ecto.Migration
+  import Ecto.Query
+  alias Pleroma.Repo
+
+  def up do
+    user_nicknames = ["relay", "internal.fetch"]
+
+    from(
+      u in "users",
+      where: u.nickname in ^user_nicknames,
+      update: [
+        set: [invisible: true]
+      ]
+    )
+    |> Repo.update_all([])
+  end
+
+  def down do
+    :ok
+  end
+end
diff --git a/test/following_relationship_test.exs b/test/following_relationship_test.exs
new file mode 100644 (file)
index 0000000..93c0798
--- /dev/null
@@ -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
index 721af1e5bb9bbecc1d677f3309dceb8126d1d1dd..98841dbbda2c231f586a3b17896ca08815f2b737 100644 (file)
@@ -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
index 8c0d45098e1fbba7559838fdc055a969d034a83e..e6302b5255c87d04dcb6ce12f7d83fac51193d4a 100644 (file)
@@ -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})
index 8fc2d93005f5cda6ec224ff92eaf078771b19581..585cb8a9e95d54b00572a949530d61e8416b9b25 100644 (file)
@@ -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