Allow to refresh instance outbox when they accept subscription

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2020-09-02 08:59:59 +02:00
parent c011a988a8
commit 489fd74545
20 changed files with 427 additions and 227 deletions

View File

@@ -51,6 +51,8 @@ defmodule Mobilizon.Federation.ActivityPub do
require Logger
@public_ap_adress "https://www.w3.org/ns/activitystreams#Public"
@doc """
Wraps an object into an activity
"""
@@ -111,10 +113,18 @@ defmodule Mobilizon.Federation.ActivityPub do
{:ok, entity}
end
with {:ok, entity} <- res do
Logger.debug("Going to preload an existing entity")
Logger.debug("Going to preload an existing entity")
Preloader.maybe_preload(entity)
case res do
{:ok, entity} ->
Preloader.maybe_preload(entity)
{:error, status, entity} ->
{:ok, entity} = Preloader.maybe_preload(entity)
{:error, status, entity}
err ->
err
end
e ->
@@ -303,7 +313,8 @@ defmodule Mobilizon.Federation.ActivityPub do
Make an actor follow another
"""
def follow(%Actor{} = follower, %Actor{} = followed, activity_id \\ nil, local \\ true) do
with {:ok, %Follower{} = follower} <-
with {:different_actors, true} <- {:different_actors, followed.id != follower.id},
{:ok, %Follower{} = follower} <-
Actors.follow(followed, follower, activity_id, false),
follower_as_data <- Convertible.model_to_as(follower),
{:ok, activity} <- create_activity(follower_as_data, local),
@@ -312,6 +323,9 @@ defmodule Mobilizon.Federation.ActivityPub do
else
{:error, err, msg} when err in [:already_following, :suspended] ->
{:error, msg}
{:different_actors, _} ->
{:error, "Can't follow yourself"}
end
end
@@ -649,7 +663,7 @@ defmodule Mobilizon.Federation.ActivityPub do
defp convert_followers_in_recipients(recipients) do
Enum.reduce(recipients, {recipients, []}, fn recipient, {recipients, follower_actors} = acc ->
case Actors.get_group_by_followers_url(recipient) do
case Actors.get_actor_by_followers_url(recipient) do
%Actor{} = group ->
{Enum.filter(recipients, fn recipient -> recipient != group.followers_url end),
follower_actors ++ Actors.list_external_followers_for_actor(group)}
@@ -797,9 +811,9 @@ defmodule Mobilizon.Federation.ActivityPub do
@spec event_to_activity(%Event{}, boolean()) :: Activity.t()
defp event_to_activity(%Event{} = event, local \\ true) do
%Activity{
recipients: ["https://www.w3.org/ns/activitystreams#Public"],
recipients: [@public_ap_adress],
actor: event.organizer_actor.url,
data: Converter.Event.model_to_as(event),
data: event |> Convertible.model_to_as() |> make_create_data(%{"to" => @public_ap_adress}),
local: local
}
end
@@ -808,9 +822,10 @@ defmodule Mobilizon.Federation.ActivityPub do
@spec comment_to_activity(%Comment{}, boolean()) :: Activity.t()
defp comment_to_activity(%Comment{} = comment, local \\ true) do
%Activity{
recipients: ["https://www.w3.org/ns/activitystreams#Public"],
recipients: [@public_ap_adress],
actor: comment.actor.url,
data: Converter.Comment.model_to_as(comment),
data:
comment |> Convertible.model_to_as() |> make_create_data(%{"to" => @public_ap_adress}),
local: local
}
end

View File

@@ -29,6 +29,7 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
{:ok, data}
else
{:ok, %Tesla.Env{status: 410}} ->
Logger.warn("Resource at #{url} is 410 Gone")
{:error, "Gone"}
{:ok, %Tesla.Env{} = res} ->

View File

@@ -6,9 +6,13 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Federation.ActivityPub.{Fetcher, Relay, Transmogrifier}
alias Mobilizon.Federation.ActivityPub.{Fetcher, Relay, Transmogrifier, Utils}
require Logger
@doc """
Refresh a remote profile
"""
@spec refresh_profile(Actor.t()) :: {:ok, Actor.t()}
def refresh_profile(%Actor{domain: nil}), do: {:error, "Can only refresh remote actors"}
def refresh_profile(%Actor{type: :Group, url: url, id: group_id} = group) do
@@ -26,8 +30,11 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do
end
end
def refresh_profile(%Actor{type: :Person, url: url}) do
ActivityPub.make_actor_from_url(url)
def refresh_profile(%Actor{type: type, url: url}) when type in [:Person, :Application] do
with {:ok, %Actor{outbox_url: outbox_url}} <- ActivityPub.make_actor_from_url(url),
:ok <- fetch_collection(outbox_url, Relay.get_actor()) do
:ok
end
end
@spec fetch_group(String.t(), Actor.t()) :: :ok
@@ -112,22 +119,13 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do
defp process_collection(_, _), do: :error
defp handling_element(data) when is_map(data) do
id = Map.get(data, "id")
object = get_in(data, ["object"])
if id do
Mobilizon.Tombstone.delete_uri_tombstone(id)
if object do
object |> Utils.get_url() |> Mobilizon.Tombstone.delete_uri_tombstone()
end
activity = %{
"type" => "Create",
"to" => data["to"],
"cc" => data["cc"],
"actor" => data["actor"],
"attributedTo" => data["attributedTo"],
"object" => data
}
Transmogrifier.handle_incoming(activity)
Transmogrifier.handle_incoming(data)
end
defp handling_element(uri) when is_binary(uri) do

View File

@@ -42,6 +42,10 @@ defmodule Mobilizon.Federation.ActivityPub.Relay do
Logger.info("Relay: followed instance #{target_instance}; id=#{activity.data["id"]}")
{:ok, activity, follow}
else
{:error, e} ->
Logger.warn("Error while following remote instance: #{inspect(e)}")
{:error, e}
e ->
Logger.warn("Error while following remote instance: #{inspect(e)}")
{:error, e}

View File

@@ -17,7 +17,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
alias Mobilizon.Todos.{Todo, TodoList}
alias Mobilizon.Federation.ActivityPub
alias Mobilizon.Federation.ActivityPub.{Activity, Relay, Utils}
alias Mobilizon.Federation.ActivityPub.{Activity, Refresher, Relay, Utils}
alias Mobilizon.Federation.ActivityPub.Types.Ownable
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
alias Mobilizon.Tombstone
@@ -656,7 +656,8 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
Handle incoming `Accept` activities wrapping a `Follow` activity
"""
def do_handle_incoming_accept_following(follow_object, %Actor{} = actor) do
with {:follow, {:ok, %Follower{approved: false, target_actor: followed} = follow}} <-
with {:follow,
{:ok, %Follower{approved: false, target_actor: followed, actor: follower} = follow}} <-
{:follow, get_follow(follow_object)},
{:same_actor, true} <- {:same_actor, actor.id == followed.id},
{:ok, %Activity{} = activity, %Follower{approved: true} = follow} <-
@@ -665,6 +666,13 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
follow,
false
) do
relay_actor = Relay.get_actor()
# If this is an instance follow, refresh the followed profile (especially their outbox)
if follower.id == relay_actor.id do
Refresher.refresh_profile(followed)
end
{:ok, activity, follow}
else
{:follow, _} ->

View File

@@ -107,15 +107,19 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
do: ["https://www.w3.org/ns/activitystreams#Public"],
else: [event.organizer_actor.followers_url]
res = %{
%{
"type" => "Event",
"to" => to,
"cc" => [],
"attributedTo" =>
if(is_nil(event.attributed_to), do: nil, else: event.attributed_to.url) ||
if(is_nil(event.attributed_to) or not Ecto.assoc_loaded?(event.attributed_to),
do: nil,
else: event.attributed_to.url
) ||
event.organizer_actor.url,
"name" => event.title,
"actor" => event.organizer_actor.url,
"actor" =>
if(Ecto.assoc_loaded?(event.organizer_actor), do: event.organizer_actor.url, else: nil),
"uuid" => event.uuid,
"category" => event.category,
"content" => event.description,
@@ -136,40 +140,9 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
"id" => event.url,
"url" => event.url
}
res =
if is_nil(event.physical_address),
do: res,
else: Map.put(res, "location", AddressConverter.model_to_as(event.physical_address))
res =
if is_nil(event.picture),
do: res,
else:
Map.update(
res,
"attachment",
[],
&(&1 ++ [PictureConverter.model_to_as(event.picture)])
)
if is_nil(event.online_address),
do: res,
else:
Map.update(
res,
"attachment",
[],
&(&1 ++
[
%{
"type" => "Link",
"href" => event.online_address,
"mediaType" => "text/html",
"name" => "Website"
}
])
)
|> maybe_add_physical_address(event)
|> maybe_add_event_picture(event)
|> maybe_add_online_address(event)
end
# Get only elements that we have in EventOptions
@@ -249,4 +222,45 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
end
end)
end
@spec maybe_add_physical_address(map(), Event.t()) :: map()
defp maybe_add_physical_address(res, event) do
if is_nil(event.physical_address),
do: res,
else: Map.put(res, "location", AddressConverter.model_to_as(event.physical_address))
end
@spec maybe_add_event_picture(map(), Event.t()) :: map()
defp maybe_add_event_picture(res, event) do
if is_nil(event.picture),
do: res,
else:
Map.update(
res,
"attachment",
[],
&(&1 ++ [PictureConverter.model_to_as(event.picture)])
)
end
@spec maybe_add_online_address(map(), Event.t()) :: map()
defp maybe_add_online_address(res, event) do
if is_nil(event.online_address),
do: res,
else:
Map.update(
res,
"attachment",
[],
&(&1 ++
[
%{
"type" => "Link",
"href" => event.online_address,
"mediaType" => "text/html",
"name" => "Website"
}
])
)
end
end