Improve group refreshment and fixed date signature generation
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -32,14 +32,14 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
|
||||
case Actors.get_actor_by_url(url, preload) do
|
||||
{:ok, %Actor{} = cached_actor} ->
|
||||
if Actors.needs_update?(cached_actor) do
|
||||
__MODULE__.make_actor_from_url(url, preload)
|
||||
__MODULE__.make_actor_from_url(url, preload: preload)
|
||||
else
|
||||
{:ok, cached_actor}
|
||||
end
|
||||
|
||||
{:error, :actor_not_found} ->
|
||||
# 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)
|
||||
__MODULE__.make_actor_from_url(url, preload: preload)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,15 +48,15 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
|
||||
@doc """
|
||||
Create an actor locally by its URL (AP ID)
|
||||
"""
|
||||
@spec make_actor_from_url(url :: String.t(), preload :: boolean()) ::
|
||||
@spec make_actor_from_url(url :: String.t(), options :: Keyword.t()) ::
|
||||
{:ok, Actor.t()} | {:error, make_actor_errors | Ecto.Changeset.t()}
|
||||
def make_actor_from_url(url, preload \\ false) do
|
||||
def make_actor_from_url(url, options \\ []) do
|
||||
if are_same_origin?(url, Endpoint.url()) do
|
||||
{:error, :actor_is_local}
|
||||
else
|
||||
case Fetcher.fetch_and_prepare_actor_from_url(url) do
|
||||
case Fetcher.fetch_and_prepare_actor_from_url(url, options) do
|
||||
{:ok, data} when is_map(data) ->
|
||||
Actors.upsert_actor(data, preload)
|
||||
Actors.upsert_actor(data, Keyword.get(options, :preload, false))
|
||||
|
||||
# Request returned 410
|
||||
{:error, :actor_deleted} ->
|
||||
@@ -78,13 +78,13 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
|
||||
case Actors.get_actor_by_name_with_preload(nickname, type) do
|
||||
%Actor{url: actor_url} = actor ->
|
||||
if Actors.needs_update?(actor) do
|
||||
make_actor_from_url(actor_url, true)
|
||||
make_actor_from_url(actor_url, preload: true)
|
||||
else
|
||||
{:ok, actor}
|
||||
end
|
||||
|
||||
nil ->
|
||||
make_actor_from_nickname(nickname, true)
|
||||
make_actor_from_nickname(nickname, preload: true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -100,7 +100,7 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
|
||||
def make_actor_from_nickname(nickname, preload \\ false) do
|
||||
case WebFinger.finger(nickname) do
|
||||
{:ok, url} when is_binary(url) ->
|
||||
make_actor_from_url(url, preload)
|
||||
make_actor_from_url(url, preload: preload)
|
||||
|
||||
{:error, e} ->
|
||||
{:error, e}
|
||||
|
||||
@@ -49,8 +49,11 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
|
||||
{:error, :content_not_json}
|
||||
|
||||
{:ok, %Tesla.Env{} = res} ->
|
||||
Logger.debug("Resource returned bad HTTP code inspect #{res}")
|
||||
Logger.debug("Resource returned bad HTTP code #{inspect(res)}")
|
||||
{:error, :http_error}
|
||||
|
||||
{:error, err} ->
|
||||
{:error, err}
|
||||
end
|
||||
else
|
||||
{:error, :invalid_url}
|
||||
@@ -122,39 +125,25 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
|
||||
"""
|
||||
@spec fetch_and_prepare_actor_from_url(String.t()) ::
|
||||
{:ok, map()} | {:error, fetch_actor_errors}
|
||||
def fetch_and_prepare_actor_from_url(url) do
|
||||
def fetch_and_prepare_actor_from_url(url, options \\ []) do
|
||||
Logger.debug("Fetching and preparing actor from url")
|
||||
Logger.debug(inspect(url))
|
||||
|
||||
case Tesla.get(url,
|
||||
headers: [{"Accept", "application/activity+json"}],
|
||||
follow_redirect: true
|
||||
) do
|
||||
{:ok, %{status: 200, body: body}} ->
|
||||
Logger.debug("response okay, now decoding json")
|
||||
case fetch(url, options) do
|
||||
{:ok, data} ->
|
||||
case ActorConverter.as_to_model_data(data) do
|
||||
{:error, :actor_not_allowed_type} ->
|
||||
{:error, :actor_not_allowed_type}
|
||||
|
||||
case Jason.decode(body) do
|
||||
{:ok, data} when is_map(data) ->
|
||||
Logger.debug("Got activity+json response at actor's endpoint, now converting data")
|
||||
|
||||
case ActorConverter.as_to_model_data(data) do
|
||||
{:error, :actor_not_allowed_type} ->
|
||||
{:error, :actor_not_allowed_type}
|
||||
|
||||
map when is_map(map) ->
|
||||
{:ok, map}
|
||||
end
|
||||
|
||||
{:error, %Jason.DecodeError{} = e} ->
|
||||
Logger.warn("Could not decode actor at fetch #{url}, #{inspect(e)}")
|
||||
{:error, :json_decode_error}
|
||||
map when is_map(map) ->
|
||||
{:ok, map}
|
||||
end
|
||||
|
||||
{:ok, %{status: 410}} ->
|
||||
{:error, :http_gone} ->
|
||||
Logger.info("Response HTTP 410")
|
||||
{:error, :actor_deleted}
|
||||
|
||||
{:ok, %Tesla.Env{}} ->
|
||||
{:error, :http_error} ->
|
||||
Logger.info("Non 200 HTTP Code")
|
||||
{:error, :http_error}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do
|
||||
|
||||
@spec fetch_group(String.t(), Actor.t()) :: :ok | {:error, fetch_actor_errors}
|
||||
def fetch_group(group_url, %Actor{} = on_behalf_of) do
|
||||
case ActivityPubActor.make_actor_from_url(group_url) do
|
||||
case ActivityPubActor.make_actor_from_url(group_url, on_behalf_of: on_behalf_of) do
|
||||
{:error, err}
|
||||
when err in [:actor_deleted, :http_error, :json_decode_error, :actor_is_local] ->
|
||||
Logger.debug("Error while making actor")
|
||||
|
||||
@@ -114,8 +114,12 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
|
||||
Logger.debug("headers")
|
||||
Logger.debug(inspect(headers))
|
||||
|
||||
with {:ok, key} <- prepare_public_key(keys) do
|
||||
HTTPSignatures.sign(key, actor.url <> "#main-key", headers)
|
||||
case prepare_public_key(keys) do
|
||||
{:ok, key} ->
|
||||
HTTPSignatures.sign(key, actor.url <> "#main-key", headers)
|
||||
|
||||
{:error, :pem_decode_error} ->
|
||||
raise ArgumentError, message: "Failed to prepare public keys for #{actor.url}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -129,7 +133,7 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do
|
||||
|
||||
@spec generate_date_header(NaiveDateTime.t()) :: String.t()
|
||||
def generate_date_header(%NaiveDateTime{} = date) do
|
||||
Timex.format!(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT")
|
||||
Timex.lformat!(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT", "en")
|
||||
end
|
||||
|
||||
@spec generate_request_target(String.t(), String.t()) :: String.t()
|
||||
|
||||
Reference in New Issue
Block a user