refetch user on incoming add/remove activity
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Wed, 3 Mar 2021 15:04:06 +0000 (18:04 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Thu, 25 Mar 2021 10:03:41 +0000 (13:03 +0300)
if featured_address is nil

lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
test/pleroma/web/activity_pub/transmogrifier_test.exs
test/support/factory.ex

index fa62e0db245b93617c0fdc8d801643c240b9644f..c4b11a65540ecf923a81768b3cbbaf4cefb2f17a 100644 (file)
@@ -558,6 +558,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def handle_incoming(%{"type" => type} = data, _options) when type in ~w(Add Remove) do
     with {:ok, %User{} = user} <- ObjectValidator.fetch_actor(data),
+         # maybe locally user doesn't have featured_address
+         {:ok, user} <- maybe_refetch_user(user),
          %Object{} <- Object.normalize(data["object"], fetch: true) do
       # Mastodon sends pin/unpin objects without id, to, cc fields
       data =
@@ -669,6 +671,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def handle_incoming(_, _), do: :error
 
+  defp maybe_refetch_user(%User{featured_address: address} = user) when is_binary(address) do
+    {:ok, user}
+  end
+
+  defp maybe_refetch_user(%User{ap_id: ap_id}), do: upgrade_user_from_ap_id(ap_id)
+
   @spec get_obj_helper(String.t(), Keyword.t()) :: {:ok, Object.t()} | nil
   def get_obj_helper(id, options \\ []) do
     options = Keyword.put(options, :fetch, true)
index d0247fa4ad90d2cd3142b81341773923177a87c9..814b3d142ba907ad01ce52947254d0a9afab9b66 100644 (file)
@@ -152,7 +152,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
       |> Enum.filter(& &1)
       |> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end)
 
-    {pinned?, pinned_at} = pin_data(activity_object, user)
+    {pinned?, pinned_at} = pin_data(object, user)
 
     %{
       id: to_string(activity.id),
index fb8284aaf250d8e7bdae8d96b9666e7add871ed8..07ed3920f74c4f4369190fc42b9115f6cf891d3d 100644 (file)
@@ -191,6 +191,84 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       user = refresh_record(user)
       refute user.pinned_objects[object_url]
     end
+
+    test "Add/Remove activities for remote users without featured address" do
+      user = insert(:user, local: false, domain: "example.com")
+
+      user =
+        user
+        |> Ecto.Changeset.change(featured_address: nil)
+        |> Repo.update!()
+
+      %{host: host} = URI.parse(user.ap_id)
+
+      user_data =
+        "test/fixtures/users_mock/user.json"
+        |> File.read!()
+        |> String.replace("{{nickname}}", user.nickname)
+
+      object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
+
+      object =
+        "test/fixtures/statuses/note.json"
+        |> File.read!()
+        |> String.replace("{{nickname}}", user.nickname)
+        |> String.replace("{{object_id}}", object_id)
+
+      object_url = "https://#{host}/objects/#{object_id}"
+
+      actor = "https://#{host}/users/#{user.nickname}"
+
+      featured = "https://#{host}/users/#{user.nickname}/collections/featured"
+
+      Tesla.Mock.mock(fn
+        %{
+          method: :get,
+          url: ^actor
+        } ->
+          %Tesla.Env{
+            status: 200,
+            body: user_data,
+            headers: [{"content-type", "application/activity+json"}]
+          }
+
+        %{
+          method: :get,
+          url: ^object_url
+        } ->
+          %Tesla.Env{
+            status: 200,
+            body: object,
+            headers: [{"content-type", "application/activity+json"}]
+          }
+
+        %{method: :get, url: ^featured} ->
+          %Tesla.Env{
+            status: 200,
+            body:
+              "test/fixtures/users_mock/masto_featured.json"
+              |> File.read!()
+              |> String.replace("{{domain}}", "#{host}")
+              |> String.replace("{{nickname}}", user.nickname),
+            headers: [{"content-type", "application/activity+json"}]
+          }
+      end)
+
+      message = %{
+        "id" => "https://#{host}/objects/d61d6733-e256-4fe1-ab13-1e369789423f",
+        "actor" => actor,
+        "object" => object_url,
+        "target" => "https://#{host}/users/#{user.nickname}/collections/featured",
+        "type" => "Add",
+        "to" => [Pleroma.Constants.as_public()],
+        "cc" => ["https://#{host}/users/#{user.nickname}/followers"]
+      }
+
+      assert {:ok, activity} = Transmogrifier.handle_incoming(message)
+      assert activity.data == message
+      user = User.get_cached_by_ap_id(actor)
+      assert user.pinned_objects[object_url]
+    end
   end
 
   describe "prepare outgoing" do
index 883cedf3c51725ac5316ae1182793e54426871bf..867076d6a986c67e446e8810419e654c9298f410 100644 (file)
@@ -41,7 +41,7 @@ defmodule Pleroma.Factory do
 
     urls =
       if attrs[:local] == false do
-        base_domain = Enum.random(["domain1.com", "domain2.com", "domain3.com"])
+        base_domain = attrs[:domain] || Enum.random(["domain1.com", "domain2.com", "domain3.com"])
 
         ap_id = "https://#{base_domain}/users/#{user.nickname}"
 
@@ -60,6 +60,8 @@ defmodule Pleroma.Factory do
         }
       end
 
+    attrs = Map.delete(attrs, :domain)
+
     user
     |> Map.put(:raw_bio, user.bio)
     |> Map.merge(urls)