federation/incoming: improve link_resolve retry decision

To facilitate this ObjectValidator.fetch_actor_and_object is adapted to
return an informative error. Otherwise we’d be unable to make an
informed decision on retrying or not later. There’s no point in
retrying to fetch MRF-blocked stuff or private posts for example.
This commit is contained in:
Oneric 2024-12-14 19:33:42 +01:00
parent 0cd4040db6
commit 2c75600532
4 changed files with 35 additions and 3 deletions

View file

@ -1999,6 +1999,10 @@ def get_or_fetch_by_ap_id(ap_id, options \\ []) do
{%User{} = user, _} ->
{:ok, user}
{_, {:error, {:reject, :mrf}}} ->
Logger.debug("Rejected to fetch user due to MRF: #{ap_id}")
{:error, {:reject, :mrf}}
e ->
Logger.error("Could not fetch user #{ap_id}, #{inspect(e)}")
{:error, :not_found}

View file

@ -15,6 +15,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.Object.Fetcher
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator
@ -253,11 +254,27 @@ def fetch_actor(object) do
end
def fetch_actor_and_object(object) do
# Fetcher.fetch_object_from_id already first does a local db lookup
with {:ok, %User{}} <- fetch_actor(object),
%Object{} <- Object.normalize(object["object"], fetch: true) do
{:ap_id, id} when is_binary(id) <-
{:ap_id, Pleroma.Web.ActivityPub.Utils.get_ap_id(object["object"])},
{:ok, %Object{}} <- Fetcher.fetch_object_from_id(id) do
:ok
else
_ -> :error
{:ap_id, id} ->
{:error, {:validate, "Invalid AP id: #{inspect(id)}"}}
# if actor: late post from a previously unknown, deleted profile
# if object: private post we're not allowed to access
# (other HTTP replies might just indicate a temporary network failure though!)
{:error, e} when e in [:not_found, :forbidden] ->
{:error, :ignore}
{:error, _} = e ->
e
e ->
{:error, e}
end
end

View file

@ -523,6 +523,15 @@ defp handle_incoming_normalised(%{"type" => type} = data, _options)
{:ok, activity, _meta} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
else
{:link, {:error, :ignore}} ->
{:error, :ignore}
{:link, {:error, {:validate, _}} = e} ->
e
{:link, {:error, {:reject, _}} = e} ->
e
{:link, _} ->
{:error, :link_resolve_failed}

View file

@ -23,6 +23,9 @@ def perform(%Job{args: %{"op" => "incoming_ap_doc", "params" => params}}) do
{:error, :already_present} ->
{:discard, :already_present}
{:error, :ignore} ->
{:discard, :ignore}
# invalid data or e.g. deleting an object we don't know about anyway
{:error, {:validate, issue}} ->
Logger.info("Received invalid AP document: #{inspect(issue)}")
@ -36,7 +39,6 @@ def perform(%Job{args: %{"op" => "incoming_ap_doc", "params" => params}}) do
# failed to resolve a necessary referenced remote AP object;
# might be temporary server/network trouble thus reattempt
{:error, :link_resolve_failed} = e ->
# TODO: lower to debug for PR!
Logger.info("Failed to resolve AP link; may retry: #{inspect(params)}")
e