Allow to refresh instance outbox when they accept subscription
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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} ->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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, _} ->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,6 +16,10 @@ defmodule Mobilizon.GraphQL.API.Follows do
|
||||
{:ok, activity, follow} ->
|
||||
{:ok, activity, follow}
|
||||
|
||||
{:error, e} ->
|
||||
Logger.warn("Error while following actor: #{inspect(e)}")
|
||||
{:error, e}
|
||||
|
||||
e ->
|
||||
Logger.warn("Error while following actor: #{inspect(e)}")
|
||||
{:error, e}
|
||||
|
||||
@@ -249,7 +249,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
|
||||
{:ok, _activity, follow} ->
|
||||
{:ok, follow}
|
||||
|
||||
{:error, {:error, err}} when is_bitstring(err) ->
|
||||
{:error, err} when is_binary(err) ->
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -561,9 +561,9 @@ defmodule Mobilizon.Actors do
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
@spec get_group_by_followers_url(String.t()) :: Actor.t()
|
||||
def get_group_by_followers_url(followers_url) do
|
||||
group_query()
|
||||
@spec get_actor_by_followers_url(String.t()) :: Actor.t()
|
||||
def get_actor_by_followers_url(followers_url) do
|
||||
Actor
|
||||
|> where([q], q.followers_url == ^followers_url)
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
@@ -251,8 +251,9 @@ defmodule Mobilizon.Events do
|
||||
def create_event(attrs \\ %{}) do
|
||||
with {:ok, %{insert: %Event{} = event}} <- do_create_event(attrs),
|
||||
%Event{} = event <- Repo.preload(event, @event_preloads) do
|
||||
unless event.draft,
|
||||
do: Workers.BuildSearch.enqueue(:insert_search_event, %{"event_id" => event.id})
|
||||
unless event.draft do
|
||||
Workers.BuildSearch.enqueue(:insert_search_event, %{"event_id" => event.id})
|
||||
end
|
||||
|
||||
{:ok, event}
|
||||
else
|
||||
|
||||
@@ -41,7 +41,10 @@ defmodule Mobilizon.Tombstone do
|
||||
|
||||
@spec find_tombstone(String.t()) :: Ecto.Schema.t() | nil
|
||||
def find_tombstone(uri) do
|
||||
Repo.get_by(__MODULE__, uri: uri)
|
||||
__MODULE__
|
||||
|> Ecto.Query.where([t], t.uri == ^uri)
|
||||
|> Ecto.Query.preload([t], [:actor])
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
@spec delete_actor_tombstones(String.t() | integer()) :: {integer(), nil}
|
||||
|
||||
@@ -30,11 +30,13 @@ defmodule Mobilizon.Service.Formatter.HTML do
|
||||
`<h1>test</h1>next` thing becomes `test next` instead of `testnext`
|
||||
"""
|
||||
@spec strip_tags_and_insert_spaces(String.t()) :: String.t()
|
||||
def strip_tags_and_insert_spaces(html) do
|
||||
def strip_tags_and_insert_spaces(html) when is_binary(html) do
|
||||
html
|
||||
|> String.replace("</", " </")
|
||||
|> strip_tags()
|
||||
end
|
||||
|
||||
def strip_tags_and_insert_spaces(html), do: html
|
||||
|
||||
def filter_tags_for_oembed(html), do: Sanitizer.scrub(html, OEmbed)
|
||||
end
|
||||
|
||||
@@ -37,6 +37,8 @@ defmodule Mobilizon.Service.Workers.Helper do
|
||||
queue: unquote(queue),
|
||||
max_attempts: 1
|
||||
|
||||
alias Oban.Job
|
||||
|
||||
def enqueue(operation, params, worker_args \\ []) do
|
||||
params = Map.merge(%{"op" => operation}, params)
|
||||
queue_atom = String.to_existing_atom(unquote(queue))
|
||||
|
||||
@@ -160,7 +160,7 @@ defmodule Mobilizon.Web.ActivityPub.ActorView do
|
||||
map
|
||||
end
|
||||
|
||||
def item(%Activity{data: %{"id" => id}}), do: id
|
||||
def item(%Activity{data: data}), do: data
|
||||
def item(%Actor{url: url}), do: url
|
||||
def item(%Member{} = member), do: Convertible.model_to_as(member)
|
||||
def item(%Resource{} = resource), do: Convertible.model_to_as(resource)
|
||||
|
||||
Reference in New Issue
Block a user