Merge branch 'following-relationships-optimizations' into 'develop'
[akkoma] / lib / pleroma / object / fetcher.ex
index 3bcbd3aea6d2ac1c9c72a5f2893c2e9c3332a225..263ded5dd50f54fa36c2e5b64576144c1b38f731 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Object.Fetcher do
@@ -10,6 +10,7 @@ defmodule Pleroma.Object.Fetcher do
   alias Pleroma.Signature
   alias Pleroma.Web.ActivityPub.InternalFetchActor
   alias Pleroma.Web.ActivityPub.Transmogrifier
+  alias Pleroma.Web.Federator
 
   require Logger
   require Pleroma.Constants
@@ -49,30 +50,33 @@ defmodule Pleroma.Object.Fetcher do
   end
 
   def refetch_object(%Object{data: %{"id" => id}} = object) do
-    with {:local, false} <- {:local, String.starts_with?(id, Pleroma.Web.base_url() <> "/")},
+    with {:local, false} <- {:local, Object.local?(object)},
          {:ok, data} <- fetch_and_contain_remote_object_from_id(id),
          {:ok, object} <- reinject_object(object, data) do
       {:ok, object}
     else
-      {:local, true} -> object
+      {:local, true} -> {:ok, object}
       e -> {:error, e}
     end
   end
 
-  # TODO:
-  # This will create a Create activity, which we need internally at the moment.
+  # Note: will create a Create activity, which we need internally at the moment.
   def fetch_object_from_id(id, options \\ []) do
-    with {:fetch_object, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
-         {:fetch, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)},
-         {:normalize, nil} <- {:normalize, Object.normalize(data, false)},
+    with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
+         {_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])},
+         {_, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)},
+         {_, nil} <- {:normalize, Object.normalize(data, false)},
          params <- prepare_activity_params(data),
-         {:containment, :ok} <- {:containment, Containment.contain_origin(id, params)},
-         {:transmogrifier, {:ok, activity}} <-
+         {_, :ok} <- {:containment, Containment.contain_origin(id, params)},
+         {_, {:ok, activity}} <-
            {:transmogrifier, Transmogrifier.handle_incoming(params, options)},
-         {:object, _data, %Object{} = object} <-
+         {_, _data, %Object{} = object} <-
            {:object, data, Object.normalize(activity, false)} do
       {:ok, object}
     else
+      {:allowed_depth, false} ->
+        {:error, "Max thread distance exceeded."}
+
       {:containment, _} ->
         {:error, "Object containment failed."}
 
@@ -117,6 +121,9 @@ defmodule Pleroma.Object.Fetcher do
       {:error, %Tesla.Mock.Error{}} ->
         nil
 
+      {:error, "Object has been deleted"} ->
+        nil
+
       e ->
         Logger.error("Error while fetching #{id}: #{inspect(e)}")
         nil
@@ -134,7 +141,7 @@ defmodule Pleroma.Object.Fetcher do
         date: date
       })
 
-    [{:Signature, signature}]
+    [{"signature", signature}]
   end
 
   defp sign_fetch(headers, id, date) do
@@ -147,19 +154,19 @@ defmodule Pleroma.Object.Fetcher do
 
   defp maybe_date_fetch(headers, date) do
     if Pleroma.Config.get([:activitypub, :sign_object_fetches]) do
-      headers ++ [{:Date, date}]
+      headers ++ [{"date", date}]
     else
       headers
     end
   end
 
   def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
-    Logger.info("Fetching object #{id} via AP")
+    Logger.debug("Fetching object #{id} via AP")
 
     date = Pleroma.Signature.signed_date()
 
     headers =
-      [{:Accept, "application/activity+json"}]
+      [{"accept", "application/activity+json"}]
       |> maybe_date_fetch(date)
       |> sign_fetch(id, date)