relay fix for admin-fe
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Tue, 18 Aug 2020 15:21:34 +0000 (18:21 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Wed, 19 Aug 2020 05:41:39 +0000 (08:41 +0300)
12 files changed:
docs/API/admin_api.md
lib/mix/tasks/pleroma/relay.ex
lib/pleroma/following_relationship.ex
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/builder.ex
lib/pleroma/web/activity_pub/relay.ex
lib/pleroma/web/admin_api/controllers/relay_controller.ex
lib/pleroma/web/api_spec/operations/admin/relay_operation.ex
test/tasks/relay_test.exs
test/web/activity_pub/activity_pub_controller_test.exs
test/web/admin_api/controllers/relay_controller_test.exs

index 05e63b528cfd529c6b5164bb571f208ada1163dc..c0ea074f089da8e228c7e548bdb0a5d6e9024f6e 100644 (file)
@@ -313,31 +313,53 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
   - On failure: `Not found`
   - On success: JSON array of user's latest statuses
 
+## `GET /api/pleroma/admin/relay`
+
+### List Relays
+
+Params: none
+Response:
+
+* On success: JSON array of relays
+
+```json
+[
+  {"actor": "https://example.com/relay", "followed_back": true},
+  {"actor": "https://example2.com/relay", "followed_back": false}
+]
+```
+
 ## `POST /api/pleroma/admin/relay`
 
 ### Follow a Relay
 
-- Params:
-  - `relay_url`
-- Response:
-  - On success: URL of the followed relay
+Params:
+
+* `relay_url`
+
+Response:
+
+* On success: relay json object
+
+```json
+{"actor": "https://example.com/relay", "followed_back": true}
+```
 
 ## `DELETE /api/pleroma/admin/relay`
 
 ### Unfollow a Relay
 
-- Params:
-  - `relay_url`
-- Response:
-  - On success: URL of the unfollowed relay
+Params:
 
-## `GET /api/pleroma/admin/relay`
+* `relay_url`
 
-### List Relays
+Response:
 
-- Params: none
-- Response:
-  - On success: JSON array of relays
+* On success: URL of the unfollowed relay
+
+```json
+{"https://example.com/relay"}
+```
 
 ## `POST /api/pleroma/admin/users/invite_token`
 
index c3312507e93786dcbebe0194177d84f9fc112c38..a6d8d6c1c872e35a3c5df60bd8a4a4bdc92ad7e5 100644 (file)
@@ -35,10 +35,16 @@ defmodule Mix.Tasks.Pleroma.Relay do
   def run(["list"]) do
     start_pleroma()
 
-    with {:ok, list} <- Relay.list(true) do
-      list |> Enum.each(&shell_info(&1))
+    with {:ok, list} <- Relay.list() do
+      Enum.each(list, &print_relay_url/1)
     else
       {:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
     end
   end
+
+  defp print_relay_url(%{followed_back: false} = relay) do
+    shell_info("#{relay.actor} - no Accept received (relay didn't follow back)")
+  end
+
+  defp print_relay_url(relay), do: shell_info(relay.actor)
 end
index 83b366dd406fc1fe8b6af93190268ff6d4694c4f..2039a259dd6e7be926e6b0f8ea77be2bbbeca1d6 100644 (file)
@@ -264,4 +264,12 @@ defmodule Pleroma.FollowingRelationship do
       end
     end)
   end
+
+  @spec following_ap_ids(User.t()) :: [String.t()]
+  def following_ap_ids(%User{} = user) do
+    user
+    |> following_query()
+    |> select([r, u], u.ap_id)
+    |> Repo.all()
+  end
 end
index a9820affa075b56efcec71dd641da27b8aa12fc9..d2ad9516f400ae1dba88afaeac6316646c1e68b0 100644 (file)
@@ -247,6 +247,13 @@ defmodule Pleroma.User do
     end
   end
 
+  defdelegate following_count(user), to: FollowingRelationship
+  defdelegate following(user), to: FollowingRelationship
+  defdelegate following?(follower, followed), to: FollowingRelationship
+  defdelegate following_ap_ids(user), to: FollowingRelationship
+  defdelegate get_follow_requests(user), to: FollowingRelationship
+  defdelegate search(query, opts \\ []), to: User.Search
+
   @doc """
   Dumps Flake Id to SQL-compatible format (16-byte UUID).
   E.g. "9pQtDGXuq4p3VlcJEm" -> <<0, 0, 1, 110, 179, 218, 42, 92, 213, 41, 44, 227, 95, 213, 0, 0>>
@@ -372,8 +379,6 @@ defmodule Pleroma.User do
     from(u in query, where: u.deactivated != ^true)
   end
 
-  defdelegate following_count(user), to: FollowingRelationship
-
   defp truncate_fields_param(params) do
     if Map.has_key?(params, :fields) do
       Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
@@ -868,8 +873,6 @@ defmodule Pleroma.User do
     set_cache(follower)
   end
 
-  defdelegate following(user), to: FollowingRelationship
-
   def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do
     deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
 
@@ -923,8 +926,6 @@ defmodule Pleroma.User do
     end
   end
 
-  defdelegate following?(follower, followed), to: FollowingRelationship
-
   @doc "Returns follow state as Pleroma.FollowingRelationship.State value"
   def get_follow_state(%User{} = follower, %User{} = following) do
     following_relationship = FollowingRelationship.get(follower, following)
@@ -1189,8 +1190,6 @@ defmodule Pleroma.User do
     |> Repo.all()
   end
 
-  defdelegate get_follow_requests(user), to: FollowingRelationship
-
   def increase_note_count(%User{} = user) do
     User
     |> where(id: ^user.id)
@@ -2163,8 +2162,6 @@ defmodule Pleroma.User do
     |> Repo.all()
   end
 
-  defdelegate search(query, opts \\ []), to: User.Search
-
   defp put_password_hash(
          %Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
        ) do
index bde1fe708a35a8f0ac310cc18a1eb3fe6d156d9a..04478bc33c01621342dd5d28e8107f848186b4ad 100644 (file)
@@ -1344,9 +1344,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   end
 
   def maybe_handle_clashing_nickname(data) do
-    nickname = data[:nickname]
-
-    with %User{} = old_user <- User.get_by_nickname(nickname),
+    with nickname when is_binary(nickname) <- data[:nickname],
+         %User{} = old_user <- User.get_by_nickname(nickname),
          {_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do
       Logger.info(
         "Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{
@@ -1360,7 +1359,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     else
       {:ap_id_comparison, true} ->
         Logger.info(
-          "Found an old user for #{nickname}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
+          "Found an old user for #{data[:nickname]}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
         )
 
       _ ->
index f2392ce79ba832036fdf5dc148a5c5d0d1e29b9b..9a7b7d9deaeff57516a89c00c46e2aecd95186a0 100644 (file)
@@ -215,7 +215,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
 
     to =
       cond do
-        actor.ap_id == Relay.relay_ap_id() ->
+        actor.ap_id == Relay.ap_id() ->
           [actor.follower_address]
 
         public? ->
index b09764d2bf647e5141bed9de5eb4d87b44a53bc5..b65710a941d1b92895a28dd58cf644fcf0d3de4f 100644 (file)
@@ -10,19 +10,13 @@ defmodule Pleroma.Web.ActivityPub.Relay do
   alias Pleroma.Web.CommonAPI
   require Logger
 
-  @relay_nickname "relay"
+  @nickname "relay"
 
-  def get_actor do
-    actor =
-      relay_ap_id()
-      |> User.get_or_create_service_actor_by_ap_id(@relay_nickname)
+  @spec ap_id() :: String.t()
+  def ap_id, do: "#{Pleroma.Web.Endpoint.url()}/#{@nickname}"
 
-    actor
-  end
-
-  def relay_ap_id do
-    "#{Pleroma.Web.Endpoint.url()}/relay"
-  end
+  @spec get_actor() :: User.t() | nil
+  def get_actor, do: User.get_or_create_service_actor_by_ap_id(ap_id(), @nickname)
 
   @spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
   def follow(target_instance) do
@@ -61,34 +55,38 @@ defmodule Pleroma.Web.ActivityPub.Relay do
 
   def publish(_), do: {:error, "Not implemented"}
 
-  @spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()}
-  def list(with_not_accepted \\ false) do
+  @spec list() :: {:ok, [%{actor: String.t(), followed_back: boolean()}]} | {:error, any()}
+  def list do
     with %User{} = user <- get_actor() do
       accepted =
         user
-        |> User.following()
-        |> Enum.map(fn entry -> URI.parse(entry).host end)
-        |> Enum.uniq()
-
-      list =
-        if with_not_accepted do
-          without_accept =
-            user
-            |> Pleroma.Activity.following_requests_for_actor()
-            |> Enum.map(fn a -> URI.parse(a.data["object"]).host <> " (no Accept received)" end)
-            |> Enum.uniq()
+        |> following()
+        |> Enum.map(fn actor -> %{actor: actor, followed_back: true} end)
 
-          accepted ++ without_accept
-        else
-          accepted
-        end
+      without_accept =
+        user
+        |> Pleroma.Activity.following_requests_for_actor()
+        |> Enum.map(fn activity -> %{actor: activity.data["object"], followed_back: false} end)
+        |> Enum.uniq()
 
-      {:ok, list}
+      {:ok, accepted ++ without_accept}
     else
       error -> format_error(error)
     end
   end
 
+  @spec following() :: [String.t()]
+  def following do
+    get_actor()
+    |> following()
+  end
+
+  defp following(user) do
+    user
+    |> User.following_ap_ids()
+    |> Enum.uniq()
+  end
+
   defp format_error({:error, error}), do: format_error(error)
 
   defp format_error(error) do
index cf9f3a14b1a2440600906a3b57977436ac0864ac..95d06dde749ba5f3f898c05fe25386ed3cd72043 100644 (file)
@@ -39,7 +39,7 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
         target: target
       })
 
-      json(conn, target)
+      json(conn, %{actor: target, followed_back: target in Relay.following()})
     else
       _ ->
         conn
index 67ee5eee02900b0a0a7db09985b902c43653edd3..e06b2d1645cc8af739de6a3937c45184e336e75e 100644 (file)
@@ -27,8 +27,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
             properties: %{
               relays: %Schema{
                 type: :array,
-                items: %Schema{type: :string},
-                example: ["lain.com", "mstdn.io"]
+                items: relay()
               }
             }
           })
@@ -43,19 +42,9 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
       operationId: "AdminAPI.RelayController.follow",
       security: [%{"oAuth" => ["write:follows"]}],
       parameters: admin_api_params(),
-      requestBody:
-        request_body("Parameters", %Schema{
-          type: :object,
-          properties: %{
-            relay_url: %Schema{type: :string, format: :uri}
-          }
-        }),
+      requestBody: request_body("Parameters", relay_url()),
       responses: %{
-        200 =>
-          Operation.response("Status", "application/json", %Schema{
-            type: :string,
-            example: "http://mastodon.example.org/users/admin"
-          })
+        200 => Operation.response("Status", "application/json", relay())
       }
     }
   end
@@ -67,13 +56,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
       operationId: "AdminAPI.RelayController.unfollow",
       security: [%{"oAuth" => ["write:follows"]}],
       parameters: admin_api_params(),
-      requestBody:
-        request_body("Parameters", %Schema{
-          type: :object,
-          properties: %{
-            relay_url: %Schema{type: :string, format: :uri}
-          }
-        }),
+      requestBody: request_body("Parameters", relay_url()),
       responses: %{
         200 =>
           Operation.response("Status", "application/json", %Schema{
@@ -83,4 +66,29 @@ defmodule Pleroma.Web.ApiSpec.Admin.RelayOperation do
       }
     }
   end
+
+  defp relay do
+    %Schema{
+      type: :object,
+      properties: %{
+        actor: %Schema{
+          type: :string,
+          example: "https://example.com/relay"
+        },
+        followed_back: %Schema{
+          type: :boolean,
+          description: "Is relay followed back by this actor?"
+        }
+      }
+    }
+  end
+
+  defp relay_url do
+    %Schema{
+      type: :object,
+      properties: %{
+        relay_url: %Schema{type: :string, format: :uri}
+      }
+    }
+  end
 end
index 79ab72002fb4229a14ac127796d3a406fe235213..e5225b64c46c2ae7834900498a895901bdb7f178 100644 (file)
@@ -42,7 +42,11 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
       assert activity.data["object"] == target_user.ap_id
 
       :ok = Mix.Tasks.Pleroma.Relay.run(["list"])
-      assert_receive {:mix_shell, :info, ["mastodon.example.org (no Accept received)"]}
+
+      assert_receive {:mix_shell, :info,
+                      [
+                        "http://mastodon.example.org/users/admin - no Accept received (relay didn't follow back)"
+                      ]}
     end
   end
 
@@ -95,8 +99,8 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
 
       :ok = Mix.Tasks.Pleroma.Relay.run(["list"])
 
-      assert_receive {:mix_shell, :info, ["mstdn.io"]}
-      assert_receive {:mix_shell, :info, ["mastodon.example.org"]}
+      assert_receive {:mix_shell, :info, ["https://mstdn.io/users/mayuutann"]}
+      assert_receive {:mix_shell, :info, ["http://mastodon.example.org/users/admin"]}
     end
   end
 end
index ed900d8f84e3261b2ce53a742f8cd99bbbe5440b..57988dc1e4f8b7ceef17d71de6ebc2ea25e20005 100644 (file)
@@ -533,7 +533,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       end)
 
       :ok = Mix.Tasks.Pleroma.Relay.run(["list"])
-      assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
+      assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]}
     end
 
     @tag capture_log: true
index 64086adc5e86712add5571ac91a729adbf824c11..adadf2b5ce71bb3231f7ce433d5893448bb2aa0e 100644 (file)
@@ -39,8 +39,10 @@ defmodule Pleroma.Web.AdminAPI.RelayControllerTest do
           relay_url: "http://mastodon.example.org/users/admin"
         })
 
-      assert json_response_and_validate_schema(conn, 200) ==
-               "http://mastodon.example.org/users/admin"
+      assert json_response_and_validate_schema(conn, 200) == %{
+               "actor" => "http://mastodon.example.org/users/admin",
+               "followed_back" => false
+             }
 
       log_entry = Repo.one(ModerationLog)
 
@@ -59,8 +61,13 @@ defmodule Pleroma.Web.AdminAPI.RelayControllerTest do
 
       conn = get(conn, "/api/pleroma/admin/relay")
 
-      assert json_response_and_validate_schema(conn, 200)["relays"] --
-               ["mastodon.example.org", "mstdn.io"] == []
+      assert json_response_and_validate_schema(conn, 200)["relays"] == [
+               %{
+                 "actor" => "http://mastodon.example.org/users/admin",
+                 "followed_back" => true
+               },
+               %{"actor" => "https://mstdn.io/users/mayuutann", "followed_back" => true}
+             ]
     end
 
     test "DELETE /relay", %{conn: conn, admin: admin} do