Don't sign fetches to instance actor when refreshing their keys

Closes #963

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-11-29 10:29:26 +01:00
parent 07d679c4ab
commit 1bfff235f3
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
4 changed files with 17 additions and 14 deletions

View file

@ -14,37 +14,38 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
@doc """ @doc """
Getting an actor from url, eventually creating it if we don't have it locally or if it needs an update Getting an actor from url, eventually creating it if we don't have it locally or if it needs an update
""" """
@spec get_or_fetch_actor_by_url(url :: String.t(), preload :: boolean()) :: @spec get_or_fetch_actor_by_url(url :: String.t(), options :: Keyword.t()) ::
{:ok, Actor.t()} {:ok, Actor.t()}
| {:error, make_actor_errors} | {:error, make_actor_errors}
| {:error, :no_internal_relay_actor} | {:error, :no_internal_relay_actor}
| {:error, :url_nil} | {:error, :url_nil}
def get_or_fetch_actor_by_url(url, preload \\ false) def get_or_fetch_actor_by_url(url, options \\ [])
def get_or_fetch_actor_by_url(nil, _preload), do: {:error, :url_nil}
def get_or_fetch_actor_by_url("https://www.w3.org/ns/activitystreams#Public", _preload) do def get_or_fetch_actor_by_url("https://www.w3.org/ns/activitystreams#Public", _preload) do
%Actor{url: url} = Relay.get_actor() %Actor{url: url} = Relay.get_actor()
get_or_fetch_actor_by_url(url) get_or_fetch_actor_by_url(url)
end end
def get_or_fetch_actor_by_url(url, preload) do def get_or_fetch_actor_by_url(url, options) when is_binary(url) and is_list(options) do
Logger.debug("Getting or fetching actor by URL #{url}") Logger.debug("Getting or fetching actor by URL #{url}")
preload = Keyword.get(options, :preload, false)
case Actors.get_actor_by_url(url, preload) do case Actors.get_actor_by_url(url, preload) do
{:ok, %Actor{} = cached_actor} -> {:ok, %Actor{} = cached_actor} ->
if Actors.needs_update?(cached_actor) do if Actors.needs_update?(cached_actor) do
__MODULE__.make_actor_from_url(url, preload: preload) __MODULE__.make_actor_from_url(url, options)
else else
{:ok, cached_actor} {:ok, cached_actor}
end end
{:error, :actor_not_found} -> {:error, :actor_not_found} ->
# For tests, see https://github.com/jjh42/mock#not-supported---mocking-internal-function-calls and Mobilizon.Federation.ActivityPubTest # For tests, see https://github.com/jjh42/mock#not-supported---mocking-internal-function-calls and Mobilizon.Federation.ActivityPubTest
__MODULE__.make_actor_from_url(url, preload: preload) __MODULE__.make_actor_from_url(url, options)
end end
end end
def get_or_fetch_actor_by_url(nil, _preload), do: {:error, :url_nil}
@type make_actor_errors :: Fetcher.fetch_actor_errors() | :actor_is_local @type make_actor_errors :: Fetcher.fetch_actor_errors() | :actor_is_local
@doc """ @doc """

View file

@ -210,7 +210,8 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
def handle_incoming( def handle_incoming(
%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = _data %{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = _data
) do ) do
with {:ok, %Actor{} = followed} <- ActivityPubActor.get_or_fetch_actor_by_url(followed, true), with {:ok, %Actor{} = followed} <-
ActivityPubActor.get_or_fetch_actor_by_url(followed, preload: true),
{:ok, %Actor{} = follower} <- ActivityPubActor.get_or_fetch_actor_by_url(follower), {:ok, %Actor{} = follower} <- ActivityPubActor.get_or_fetch_actor_by_url(follower),
{:ok, activity, object} <- {:ok, activity, object} <-
Actions.Follow.follow(follower, followed, id, false) do Actions.Follow.follow(follower, followed, id, false) do

View file

@ -52,7 +52,8 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
{:ok, String.t()} {:ok, String.t()}
| {:error, :actor_not_found | :pem_decode_error} | {:error, :actor_not_found | :pem_decode_error}
defp get_public_key_for_url(url) do defp get_public_key_for_url(url) do
with {:ok, %Actor{} = actor} <- ActivityPubActor.get_or_fetch_actor_by_url(url) do with {:ok, %Actor{} = actor} <-
ActivityPubActor.get_or_fetch_actor_by_url(url, ignore_sign_object_fetches: true) do
get_actor_public_key(actor) get_actor_public_key(actor)
end end
end end

View file

@ -126,7 +126,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
needs_update?: fn _ -> false end needs_update?: fn _ -> false end
]}, ]},
{ActivityPubActor, [:passthrough], {ActivityPubActor, [:passthrough],
make_actor_from_url: fn @actor_url, preload: false -> make_actor_from_url: fn @actor_url, [] ->
{:ok, {:ok,
%Actor{ %Actor{
preferred_username: "tcit", preferred_username: "tcit",
@ -138,7 +138,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
ActivityPubActor.get_or_fetch_actor_by_url(@actor_url) ActivityPubActor.get_or_fetch_actor_by_url(@actor_url)
assert_called(Actors.needs_update?(:_)) assert_called(Actors.needs_update?(:_))
refute called(ActivityPubActor.make_actor_from_url(@actor_url, preload: false)) refute called(ActivityPubActor.make_actor_from_url(@actor_url, []))
end end
# Fetch doesn't use cache if Actors.needs_update? returns true # Fetch doesn't use cache if Actors.needs_update? returns true
@ -155,7 +155,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
needs_update?: fn _ -> true end needs_update?: fn _ -> true end
]}, ]},
{ActivityPubActor, [:passthrough], {ActivityPubActor, [:passthrough],
make_actor_from_url: fn @actor_url, preload: false -> make_actor_from_url: fn @actor_url, [] ->
{:ok, {:ok,
%Actor{ %Actor{
preferred_username: "tcit", preferred_username: "tcit",
@ -169,7 +169,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
assert_called(ActivityPubActor.get_or_fetch_actor_by_url(@actor_url)) assert_called(ActivityPubActor.get_or_fetch_actor_by_url(@actor_url))
assert_called(Actors.get_actor_by_url(@actor_url, false)) assert_called(Actors.get_actor_by_url(@actor_url, false))
assert_called(Actors.needs_update?(:_)) assert_called(Actors.needs_update?(:_))
assert_called(ActivityPubActor.make_actor_from_url(@actor_url, preload: false)) assert_called(ActivityPubActor.make_actor_from_url(@actor_url, []))
end end
end end
@ -182,7 +182,7 @@ defmodule Mobilizon.Federation.ActivityPub.ActorTest do
assert match?( assert match?(
{:error, :actor_deleted}, {:error, :actor_deleted},
ActivityPubActor.make_actor_from_url(@actor_url, preload: false) ActivityPubActor.make_actor_from_url(@actor_url, [])
) )
end end