relay list shows hosts without accepted follow
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Tue, 25 Feb 2020 13:21:48 +0000 (16:21 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Mon, 2 Mar 2020 06:27:20 +0000 (09:27 +0300)
lib/mix/tasks/pleroma/relay.ex
lib/pleroma/activity.ex
lib/pleroma/web/activity_pub/relay.ex
test/fixtures/relay/accept-follow.json [new file with mode: 0644]
test/fixtures/relay/relay.json [new file with mode: 0644]
test/support/http_request_mock.ex
test/tasks/relay_test.exs
test/web/activity_pub/activity_pub_controller_test.exs

index 7ef5f9678534a8669cb434910d5b56a78b7866f3..b0fadeae9b8bdd752683b4e5a39a2c16dc85cc7a 100644 (file)
@@ -35,7 +35,7 @@ defmodule Mix.Tasks.Pleroma.Relay do
   def run(["list"]) do
     start_pleroma()
 
-    with {:ok, list} <- Relay.list() do
+    with {:ok, list} <- Relay.list(true) do
       list |> Enum.each(&shell_info(&1))
     else
       {:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
index 397eb6e3f614bafe8140152682b7f422797f94a2..6ca05f74e061ce4739b52fe592db979cc92408b5 100644 (file)
@@ -308,6 +308,13 @@ defmodule Pleroma.Activity do
     |> where([a], fragment("? ->> 'state' = 'pending'", a.data))
   end
 
+  def following_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do
+    Queries.by_type("Follow")
+    |> where([a], fragment("?->>'state' = 'pending'", a.data))
+    |> where([a], a.actor == ^ap_id)
+    |> Repo.all()
+  end
+
   def restrict_deactivated_users(query) do
     deactivated_users =
       from(u in User.Query.build(%{deactivated: true}), select: u.ap_id)
index bb5542c89f880e21aefcb6156ccfe4e3f6ca34c9..729c23af7c275f8f5956134381cb17a9f8acc8f5 100644 (file)
@@ -60,15 +60,28 @@ defmodule Pleroma.Web.ActivityPub.Relay do
 
   def publish(_), do: {:error, "Not implemented"}
 
-  @spec list() :: {:ok, [String.t()]} | {:error, any()}
-  def list do
+  @spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()}
+  def list(with_not_accepted \\ false) do
     with %User{} = user <- get_actor() do
-      list =
+      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()
+
+          accepted ++ without_accept
+        else
+          accepted
+        end
+
       {:ok, list}
     else
       error -> format_error(error)
diff --git a/test/fixtures/relay/accept-follow.json b/test/fixtures/relay/accept-follow.json
new file mode 100644 (file)
index 0000000..1b166f2
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "@context": "https://www.w3.org/ns/activitystreams",
+  "actor": "https://relay.mastodon.host/actor",
+  "id": "https://relay.mastodon.host/activities/ec477b69-db26-4019-923e-cf809de516ab",
+  "object": {
+    "actor": "{{ap_id}}",
+    "id": "{{activity_id}}",
+    "object": "https://relay.mastodon.host/actor",
+    "type": "Follow"
+  },
+  "to": [
+    "{{ap_id}}"
+  ],
+  "type": "Accept"
+}
\ No newline at end of file
diff --git a/test/fixtures/relay/relay.json b/test/fixtures/relay/relay.json
new file mode 100644 (file)
index 0000000..77ae7f0
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "@context": "https://www.w3.org/ns/activitystreams",
+  "endpoints": {
+    "sharedInbox": "https://relay.mastodon.host/inbox"
+  },
+  "followers": "https://relay.mastodon.host/followers",
+  "following": "https://relay.mastodon.host/following",
+  "inbox": "https://relay.mastodon.host/inbox",
+  "name": "ActivityRelay",
+  "type": "Application",
+  "id": "https://relay.mastodon.host/actor",
+  "publicKey": {
+    "id": "https://relay.mastodon.host/actor#main-key",
+    "owner": "https://relay.mastodon.host/actor",
+    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNYHNYETdsZFsdcTTEQo\nlsTP9yz4ZjOGrQ1EjoBA7NkjBUxxUAPxZbBjWPT9F+L3IbCX1IwI2OrBM/KwDlug\nV41xnjNmxSCUNpxX5IMZtFaAz9/hWu6xkRTs9Bh6XWZxi+db905aOqszb9Mo3H2g\nQJiAYemXwTh2kBO7XlBDbsMhO11Tu8FxcWTMdR54vlGv4RoiVh8dJRa06yyiTs+m\njbj/OJwR06mHHwlKYTVT/587NUb+e9QtCK6t/dqpyZ1o7vKSK5PSldZVjwHt292E\nXVxFOQVXi7JazTwpdPww79ECSe8ThCykOYCNkm3RjsKuLuokp7Vzq1hXIoeBJ7z2\ndU8vbgg/JyazsOsTxkVs2nd2i9/QW2SH+sX9X3357+XLSCh/A8p8fv/GeoN7UCXe\n4DWHFJZDlItNFfymiPbQH+omuju8qrfW9ngk1gFeI2mahXFQVu7x0qsaZYioCIrZ\nwq0zPnUGl9u0tLUXQz+ZkInRrEz+JepDVauy5/3QdzMLG420zCj/ygDrFzpBQIrc\n62Z6URueUBJox0UK71K+usxqOrepgw8haFGMvg3STFo34pNYjoK4oKO+h5qZEDFD\nb1n57t6JWUaBocZbJns9RGASq5gih+iMk2+zPLWp1x64yvuLsYVLPLBHxjCxS6lA\ndWcopZHi7R/OsRz+vTT7420CAwEAAQ==\n-----END PUBLIC KEY-----"
+  },
+  "summary": "ActivityRelay bot",
+  "preferredUsername": "relay",
+  "url": "https://relay.mastodon.host/actor"
+}
\ No newline at end of file
index d4688786523f40aeeafbd06fa1ebb03af3d2262b..e72638814804b765b48763417eaeaaf0cffe477c 100644 (file)
@@ -1277,6 +1277,10 @@ defmodule HttpRequestMock do
     {:ok, %Tesla.Env{status: 404, body: ""}}
   end
 
+  def get("https://relay.mastodon.host/actor", _, _, _) do
+    {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/relay/relay.json")}}
+  end
+
   def get(url, query, body, headers) do
     {:error,
      "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
@@ -1289,6 +1293,10 @@ defmodule HttpRequestMock do
 
   def post(url, query \\ [], body \\ [], headers \\ [])
 
+  def post("https://relay.mastodon.host/inbox", _, _, _) do
+    {:ok, %Tesla.Env{status: 200, body: ""}}
+  end
+
   def post("http://example.org/needs_refresh", _, _, _) do
     {:ok,
      %Tesla.Env{
index 04a1e45d7ef6524070b10713b6222a249cb067a7..43565b7c7403f2efef1aa9d6120d7d3a8f223d4e 100644 (file)
@@ -38,6 +38,9 @@ defmodule Mix.Tasks.Pleroma.RelayTest do
       assert activity.data["type"] == "Follow"
       assert activity.data["actor"] == local_user.ap_id
       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)"]}
     end
   end
 
index ba2ce1dd9157e5ea3ac854398a11208968969a1a..0c80e2434c686b765957bbdbf53ff0f7e8967542 100644 (file)
@@ -341,6 +341,44 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
       assert "ok" == json_response(conn, 200)
       assert Instances.reachable?(sender_url)
     end
+
+    test "accept follow activity", %{conn: conn} do
+      Pleroma.Config.put([:instance, :federating], true)
+      relay = Relay.get_actor()
+
+      assert {:ok, %Activity{} = activity} = Relay.follow("https://relay.mastodon.host/actor")
+
+      followed_relay = Pleroma.User.get_by_ap_id("https://relay.mastodon.host/actor")
+      relay = refresh_record(relay)
+
+      accept =
+        File.read!("test/fixtures/relay/accept-follow.json")
+        |> String.replace("{{ap_id}}", relay.ap_id)
+        |> String.replace("{{activity_id}}", activity.data["id"])
+
+      assert "ok" ==
+               conn
+               |> assign(:valid_signature, true)
+               |> put_req_header("content-type", "application/activity+json")
+               |> post("/inbox", accept)
+               |> json_response(200)
+
+      ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
+
+      assert Pleroma.FollowingRelationship.following?(
+               relay,
+               followed_relay
+             )
+
+      Mix.shell(Mix.Shell.Process)
+
+      on_exit(fn ->
+        Mix.shell(Mix.Shell.IO)
+      end)
+
+      :ok = Mix.Tasks.Pleroma.Relay.run(["list"])
+      assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
+    end
   end
 
   describe "/users/:nickname/inbox" do