Merge branch 'remove-multiple-federator-modules' into 'develop'

Remove support for multiple federation publisher modules

See merge request pleroma/pleroma!4019
This commit is contained in:
Haelwenn 2023-12-29 03:35:24 +00:00
commit 7f3a83d3ed
10 changed files with 60 additions and 141 deletions

View File

@ -0,0 +1 @@
Removed support for multiple federator modules as we only support ActivityPub

View File

@ -192,9 +192,6 @@
federating: true, federating: true,
federation_incoming_replies_max_depth: 100, federation_incoming_replies_max_depth: 100,
federation_reachability_timeout_days: 7, federation_reachability_timeout_days: 7,
federation_publisher_modules: [
Pleroma.Web.ActivityPub.Publisher
],
allow_relay: true, allow_relay: true,
public: true, public: true,
quarantined_instances: [], quarantined_instances: [],

View File

@ -13,19 +13,56 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Workers.PublisherWorker
require Pleroma.Constants require Pleroma.Constants
import Pleroma.Web.ActivityPub.Visibility import Pleroma.Web.ActivityPub.Visibility
@behaviour Pleroma.Web.Federator.Publisher
require Logger require Logger
@moduledoc """ @moduledoc """
ActivityPub outgoing federation module. ActivityPub outgoing federation module.
""" """
@doc """
Enqueue publishing a single activity.
"""
@spec enqueue_one(Map.t(), Keyword.t()) :: {:ok, %Oban.Job{}}
def enqueue_one(%{} = params, worker_args \\ []) do
PublisherWorker.enqueue(
"publish_one",
%{"params" => params},
worker_args
)
end
@doc """
Gathers a set of remote users given an IR envelope.
"""
def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do
cc = Map.get(data, "cc", [])
bcc =
data
|> Map.get("bcc", [])
|> Enum.reduce([], fn ap_id, bcc ->
case Pleroma.List.get_by_ap_id(ap_id) do
%Pleroma.List{user_id: ^user_id} = list ->
{:ok, following} = Pleroma.List.get_following(list)
bcc ++ Enum.map(following, & &1.ap_id)
_ ->
bcc
end
end)
[to, cc, bcc]
|> Enum.concat()
|> Enum.map(&User.get_cached_by_ap_id/1)
|> Enum.filter(fn user -> user && !user.local end)
end
@doc """ @doc """
Determine if an activity can be represented by running it through Transmogrifier. Determine if an activity can be represented by running it through Transmogrifier.
""" """
@ -138,7 +175,7 @@ defp recipients(actor, activity) do
[] []
end end
mentioned = Pleroma.Web.Federator.Publisher.remote_users(actor, activity) mentioned = remote_users(actor, activity)
non_mentioned = (followers ++ fetchers) -- mentioned non_mentioned = (followers ++ fetchers) -- mentioned
[mentioned, non_mentioned] [mentioned, non_mentioned]
@ -223,7 +260,7 @@ def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
|> Map.put("cc", cc) |> Map.put("cc", cc)
|> Jason.encode!() |> Jason.encode!()
Pleroma.Web.Federator.Publisher.enqueue_one(__MODULE__, %{ __MODULE__.enqueue_one(%{
inbox: inbox, inbox: inbox,
json: json, json: json,
actor_id: actor.id, actor_id: actor.id,
@ -262,8 +299,7 @@ def publish(%User{} = actor, %Activity{} = activity) do
inboxes inboxes
|> Instances.filter_reachable() |> Instances.filter_reachable()
|> Enum.each(fn {inbox, unreachable_since} -> |> Enum.each(fn {inbox, unreachable_since} ->
Pleroma.Web.Federator.Publisher.enqueue_one( __MODULE__.enqueue_one(
__MODULE__,
%{ %{
inbox: inbox, inbox: inbox,
json: json, json: json,

View File

@ -6,9 +6,9 @@ defmodule Pleroma.Web.Federator do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Object.Containment alias Pleroma.Object.Containment
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Publisher
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Federator.Publisher
alias Pleroma.Workers.PublisherWorker alias Pleroma.Workers.PublisherWorker
alias Pleroma.Workers.ReceiverWorker alias Pleroma.Workers.ReceiverWorker

View File

@ -1,110 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Federator.Publisher do
alias Pleroma.Activity
alias Pleroma.Config
alias Pleroma.User
alias Pleroma.Workers.PublisherWorker
require Logger
@moduledoc """
Defines the contract used by federation implementations to publish messages to
their peers.
"""
@doc """
Determine whether an activity can be relayed using the federation module.
"""
@callback is_representable?(Pleroma.Activity.t()) :: boolean()
@doc """
Relays an activity to a specified peer, determined by the parameters. The
parameters used are controlled by the federation module.
"""
@callback publish_one(Map.t()) :: {:ok, Map.t()} | {:error, any()}
@doc """
Enqueue publishing a single activity.
"""
@spec enqueue_one(module(), Map.t(), Keyword.t()) :: {:ok, %Oban.Job{}}
def enqueue_one(module, %{} = params, worker_args \\ []) do
PublisherWorker.enqueue(
"publish_one",
%{"module" => to_string(module), "params" => params},
worker_args
)
end
@doc """
Relays an activity to all specified peers.
"""
@callback publish(User.t(), Activity.t()) :: :ok | {:error, any()}
@spec publish(User.t(), Activity.t()) :: :ok
def publish(%User{} = user, %Activity{} = activity) do
Config.get([:instance, :federation_publisher_modules])
|> Enum.each(fn module ->
if module.is_representable?(activity) do
Logger.debug("Publishing #{activity.data["id"]} using #{inspect(module)}")
module.publish(user, activity)
end
end)
:ok
end
@doc """
Gathers links used by an outgoing federation module for WebFinger output.
"""
@callback gather_webfinger_links(User.t()) :: list()
@spec gather_webfinger_links(User.t()) :: list()
def gather_webfinger_links(%User{} = user) do
Config.get([:instance, :federation_publisher_modules])
|> Enum.reduce([], fn module, links ->
links ++ module.gather_webfinger_links(user)
end)
end
@doc """
Gathers nodeinfo protocol names supported by the federation module.
"""
@callback gather_nodeinfo_protocol_names() :: list()
@spec gather_nodeinfo_protocol_names() :: list()
def gather_nodeinfo_protocol_names do
Config.get([:instance, :federation_publisher_modules])
|> Enum.reduce([], fn module, links ->
links ++ module.gather_nodeinfo_protocol_names()
end)
end
@doc """
Gathers a set of remote users given an IR envelope.
"""
def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do
cc = Map.get(data, "cc", [])
bcc =
data
|> Map.get("bcc", [])
|> Enum.reduce([], fn ap_id, bcc ->
case Pleroma.List.get_by_ap_id(ap_id) do
%Pleroma.List{user_id: ^user_id} = list ->
{:ok, following} = Pleroma.List.get_following(list)
bcc ++ Enum.map(following, & &1.ap_id)
_ ->
bcc
end
end)
[to, cc, bcc]
|> Enum.concat()
|> Enum.map(&User.get_cached_by_ap_id/1)
|> Enum.filter(fn user -> user && !user.local end)
end
end

View File

@ -6,7 +6,7 @@ defmodule Pleroma.Web.Nodeinfo.Nodeinfo do
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Stats alias Pleroma.Stats
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.Federator.Publisher alias Pleroma.Web.ActivityPub.Publisher
alias Pleroma.Web.MastodonAPI.InstanceView alias Pleroma.Web.MastodonAPI.InstanceView
# returns a nodeinfo 2.0 map, since 2.1 just adds a repository field # returns a nodeinfo 2.0 map, since 2.1 just adds a repository field

View File

@ -5,8 +5,8 @@
defmodule Pleroma.Web.WebFinger do defmodule Pleroma.Web.WebFinger do
alias Pleroma.HTTP alias Pleroma.HTTP
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Publisher
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
alias Pleroma.Web.Federator.Publisher
alias Pleroma.Web.XML alias Pleroma.Web.XML
alias Pleroma.XmlBuilder alias Pleroma.XmlBuilder
require Jason require Jason

View File

@ -18,9 +18,9 @@ def perform(%Job{args: %{"op" => "publish", "activity_id" => activity_id}}) do
Federator.perform(:publish, activity) Federator.perform(:publish, activity)
end end
def perform(%Job{args: %{"op" => "publish_one", "module" => module_name, "params" => params}}) do def perform(%Job{args: %{"op" => "publish_one", "params" => params}}) do
params = Map.new(params, fn {k, v} -> {String.to_atom(k), v} end) params = Map.new(params, fn {k, v} -> {String.to_atom(k), v} end)
Federator.perform(:publish_one, String.to_atom(module_name), params) Federator.perform(:publish_one, params)
end end
@impl Oban.Worker @impl Oban.Worker

View File

@ -140,7 +140,6 @@ test "load a settings with large values and pass to file", %{temp_file: temp_fil
federating: true, federating: true,
federation_incoming_replies_max_depth: 100, federation_incoming_replies_max_depth: 100,
federation_reachability_timeout_days: 7, federation_reachability_timeout_days: 7,
federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],
allow_relay: true, allow_relay: true,
public: true, public: true,
quarantined_instances: [], quarantined_instances: [],
@ -184,7 +183,7 @@ test "load a settings with large values and pass to file", %{temp_file: temp_fil
{:ok, file} = File.read(temp_file) {:ok, file} = File.read(temp_file)
assert file == assert file ==
"import Config\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" "import Config\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n"
end end
end end

View File

@ -268,7 +268,7 @@ test "publish to url with with different ports" do
describe "publish/2" do describe "publish/2" do
test_with_mock "doesn't publish a non-public activity to quarantined instances.", test_with_mock "doesn't publish a non-public activity to quarantined instances.",
Pleroma.Web.Federator.Publisher, Pleroma.Web.ActivityPub.Publisher,
[:passthrough], [:passthrough],
[] do [] do
Config.put([:instance, :quarantined_instances], [{"domain.com", "some reason"}]) Config.put([:instance, :quarantined_instances], [{"domain.com", "some reason"}])
@ -295,7 +295,7 @@ test "publish to url with with different ports" do
assert res == :ok assert res == :ok
assert not called( assert not called(
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{ Publisher.enqueue_one(%{
inbox: "https://domain.com/users/nick1/inbox", inbox: "https://domain.com/users/nick1/inbox",
actor_id: actor.id, actor_id: actor.id,
id: note_activity.data["id"] id: note_activity.data["id"]
@ -304,7 +304,7 @@ test "publish to url with with different ports" do
end end
test_with_mock "Publishes a non-public activity to non-quarantined instances.", test_with_mock "Publishes a non-public activity to non-quarantined instances.",
Pleroma.Web.Federator.Publisher, Pleroma.Web.ActivityPub.Publisher,
[:passthrough], [:passthrough],
[] do [] do
Config.put([:instance, :quarantined_instances], [{"somedomain.com", "some reason"}]) Config.put([:instance, :quarantined_instances], [{"somedomain.com", "some reason"}])
@ -331,8 +331,7 @@ test "publish to url with with different ports" do
assert res == :ok assert res == :ok
assert called( assert called(
Pleroma.Web.Federator.Publisher.enqueue_one( Publisher.enqueue_one(
Publisher,
%{ %{
inbox: "https://domain.com/users/nick1/inbox", inbox: "https://domain.com/users/nick1/inbox",
actor_id: actor.id, actor_id: actor.id,
@ -344,7 +343,7 @@ test "publish to url with with different ports" do
end end
test_with_mock "Publishes to directly addressed actors with higher priority.", test_with_mock "Publishes to directly addressed actors with higher priority.",
Pleroma.Web.Federator.Publisher, Pleroma.Web.ActivityPub.Publisher,
[:passthrough], [:passthrough],
[] do [] do
note_activity = insert(:direct_note_activity) note_activity = insert(:direct_note_activity)
@ -356,8 +355,7 @@ test "publish to url with with different ports" do
assert res == :ok assert res == :ok
assert called( assert called(
Pleroma.Web.Federator.Publisher.enqueue_one( Publisher.enqueue_one(
Publisher,
%{ %{
inbox: :_, inbox: :_,
actor_id: actor.id, actor_id: actor.id,
@ -369,7 +367,7 @@ test "publish to url with with different ports" do
end end
test_with_mock "publishes an activity with BCC to all relevant peers.", test_with_mock "publishes an activity with BCC to all relevant peers.",
Pleroma.Web.Federator.Publisher, Pleroma.Web.ActivityPub.Publisher,
[:passthrough], [:passthrough],
[] do [] do
follower = follower =
@ -393,7 +391,7 @@ test "publish to url with with different ports" do
assert res == :ok assert res == :ok
assert called( assert called(
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{ Publisher.enqueue_one(%{
inbox: "https://domain.com/users/nick1/inbox", inbox: "https://domain.com/users/nick1/inbox",
actor_id: actor.id, actor_id: actor.id,
id: note_activity.data["id"] id: note_activity.data["id"]
@ -402,7 +400,7 @@ test "publish to url with with different ports" do
end end
test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.", test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.",
Pleroma.Web.Federator.Publisher, Pleroma.Web.ActivityPub.Publisher,
[:passthrough], [:passthrough],
[] do [] do
fetcher = fetcher =
@ -443,8 +441,7 @@ test "publish to url with with different ports" do
assert res == :ok assert res == :ok
assert called( assert called(
Pleroma.Web.Federator.Publisher.enqueue_one( Publisher.enqueue_one(
Publisher,
%{ %{
inbox: "https://domain.com/users/nick1/inbox", inbox: "https://domain.com/users/nick1/inbox",
actor_id: actor.id, actor_id: actor.id,
@ -455,8 +452,7 @@ test "publish to url with with different ports" do
) )
assert called( assert called(
Pleroma.Web.Federator.Publisher.enqueue_one( Publisher.enqueue_one(
Publisher,
%{ %{
inbox: "https://domain2.com/users/nick1/inbox", inbox: "https://domain2.com/users/nick1/inbox",
actor_id: actor.id, actor_id: actor.id,