summaryrefslogtreecommitdiff
path: root/lib/pleroma/web/activity_pub
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/activity_pub')
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex27
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/drop_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/emoji_policy.ex30
-rw-r--r--lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex53
-rw-r--r--lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex20
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_mention.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex51
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex54
-rw-r--r--lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/keyword_policy.ex48
-rw-r--r--lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/mention_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_op_policy.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex8
-rw-r--r--lib/pleroma/web/activity_pub/mrf/normalize_markup.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex48
-rw-r--r--lib/pleroma/web/activity_pub/mrf/object_age_policy.ex58
-rw-r--r--lib/pleroma/web/activity_pub/mrf/policy.ex5
-rw-r--r--lib/pleroma/web/activity_pub/mrf/quiet_reply.ex60
-rw-r--r--lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex118
-rw-r--r--lib/pleroma/web/activity_pub/mrf/simple_policy.ex162
-rw-r--r--lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex6
-rw-r--r--lib/pleroma/web/activity_pub/mrf/subchain_policy.ex10
-rw-r--r--lib/pleroma/web/activity_pub/mrf/tag_policy.ex62
-rw-r--r--lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex30
-rw-r--r--lib/pleroma/web/activity_pub/object_validator.ex12
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/block_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/follow_validator.ex2
-rw-r--r--lib/pleroma/web/activity_pub/pipeline.ex19
-rw-r--r--lib/pleroma/web/activity_pub/publisher.ex72
-rw-r--r--lib/pleroma/web/activity_pub/publisher/prepared.ex8
-rw-r--r--lib/pleroma/web/activity_pub/side_effects.ex14
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex36
46 files changed, 774 insertions, 421 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index b30b0cabe..df8795fe4 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -222,10 +222,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
%{data: %{"expires_at" => %DateTime{} = expires_at}} = activity
) do
with {:ok, _job} <-
- Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
- activity_id: activity.id,
- expires_at: expires_at
- }) do
+ Pleroma.Workers.PurgeExpiredActivity.enqueue(
+ %{
+ activity_id: activity.id
+ },
+ scheduled_at: expires_at
+ ) do
{:ok, activity}
end
end
@@ -446,10 +448,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
_ <- notify_and_stream(activity) do
maybe_federate(activity)
- BackgroundWorker.enqueue("move_following", %{
+ BackgroundWorker.new(%{
+ "op" => "move_following",
"origin_id" => origin.id,
"target_id" => target.id
})
+ |> Oban.insert()
{:ok, activity}
else
@@ -1538,16 +1542,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp get_actor_url(_url), do: nil
- defp normalize_image(%{"url" => url}) do
+ defp normalize_image(%{"url" => url} = data) do
%{
"type" => "Image",
"url" => [%{"href" => url}]
}
+ |> maybe_put_description(data)
end
defp normalize_image(urls) when is_list(urls), do: urls |> List.first() |> normalize_image()
defp normalize_image(_), do: nil
+ defp maybe_put_description(map, %{"name" => description}) when is_binary(description) do
+ Map.put(map, "name", description)
+ end
+
+ defp maybe_put_description(map, _), do: map
+
defp object_to_user_data(data, additional) do
fields =
data
@@ -1797,10 +1808,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# enqueue a task to fetch all pinned objects
Enum.each(pins, fn {ap_id, _} ->
if is_nil(Object.get_cached_by_ap_id(ap_id)) do
- Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
+ Pleroma.Workers.RemoteFetcherWorker.new(%{
+ "op" => "fetch_remote",
"id" => ap_id,
"depth" => 1
})
+ |> Oban.insert()
end
end)
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index cdd054e1a..a08eda5f4 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -311,7 +311,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
post_inbox_relayed_create(conn, params)
else
conn
- |> put_status(:bad_request)
+ |> put_status(403)
|> json("Not federating")
end
end
diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex
index bc418d908..51ab476b7 100644
--- a/lib/pleroma/web/activity_pub/mrf.ex
+++ b/lib/pleroma/web/activity_pub/mrf.ex
@@ -108,6 +108,14 @@ defmodule Pleroma.Web.ActivityPub.MRF do
def filter(%{} = object), do: get_policies() |> filter(object)
+ def id_filter(policies, id) when is_binary(id) do
+ policies
+ |> Enum.filter(&function_exported?(&1, :id_filter, 1))
+ |> Enum.all?(& &1.id_filter(id))
+ end
+
+ def id_filter(id) when is_binary(id), do: get_policies() |> id_filter(id)
+
@impl true
def pipeline_filter(%{} = message, meta) do
object = meta[:object_data]
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
index df4ba819c..8ea61aec2 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
@@ -63,20 +63,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
end
@impl true
- def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
+ def filter(%{"type" => "Follow", "actor" => actor_id} = activity) do
%User{} = actor = normalize_by_ap_id(actor_id)
score = determine_if_followbot(actor)
- if score < 0.8 || bot_allowed?(message, actor) do
- {:ok, message}
+ if score < 0.8 || bot_allowed?(activity, actor) do
+ {:ok, activity}
else
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
index 3ec9c52ee..2be6d8df4 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
@@ -29,17 +29,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
defp contains_links?(_), do: false
@impl true
- def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
+ def filter(%{"type" => "Create", "actor" => actor, "object" => object} = activity) do
with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
{:contains_links, true} <- {:contains_links, contains_links?(object)},
{:old_user, true} <- {:old_user, old_user?(u)} do
- {:ok, message}
+ {:ok, activity}
else
{:ok, %User{local: true}} ->
- {:ok, message}
+ {:ok, activity}
{:contains_links, false} ->
- {:ok, message}
+ {:ok, activity}
{:old_user, false} ->
{:reject, "[AntiLinkSpamPolicy] User has no posts nor followers"}
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
end
# in all other cases, pass through
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
index 531e75ce8..1d76a307b 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
@@ -22,11 +22,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
end
# copied from HellthreadPolicy
- defp get_recipient_count(message) do
- recipients = (message["to"] || []) ++ (message["cc"] || [])
+ defp get_recipient_count(activity) do
+ recipients = (activity["to"] || []) ++ (activity["cc"] || [])
follower_collection =
- User.get_cached_by_ap_id(message["actor"] || message["attributedTo"]).follower_address
+ User.get_cached_by_ap_id(activity["actor"] || activity["attributedTo"]).follower_address
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
recipients =
@@ -80,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
end
# in all other cases, pass through
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex b/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex
index 7c6bb888f..ca41c464c 100644
--- a/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/dnsrbl_policy.ex
@@ -38,18 +38,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
@query_timeout 500
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
actor_info = URI.parse(actor)
- with {:ok, object} <- check_rbl(actor_info, object) do
- {:ok, object}
+ with {:ok, activity} <- check_rbl(actor_info, activity) do
+ {:ok, activity}
else
_ -> {:reject, "[DNSRBLPolicy]"}
end
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
}
end
- defp check_rbl(%{host: actor_host}, object) do
+ defp check_rbl(%{host: actor_host}, activity) do
with false <- match?(^actor_host, Pleroma.Web.Endpoint.host()),
zone when not is_nil(zone) <- Keyword.get(Config.get([:mrf_dnsrbl]), :zone) do
query =
@@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
rbl_response = rblquery(query)
if Enum.empty?(rbl_response) do
- {:ok, object}
+ {:ok, activity}
else
Task.start(fn ->
reason =
@@ -117,7 +117,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
:error
end
else
- _ -> {:ok, object}
+ _ -> {:ok, activity}
end
end
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
index ad0936839..cf07db7f3 100644
--- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
@@ -8,9 +8,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(object) do
- Logger.debug("REJECTING #{inspect(object)}")
- {:reject, object}
+ def filter(activity) do
+ Logger.debug("REJECTING #{inspect(activity)}")
+ {:reject, activity}
+ end
+
+ @impl true
+ def id_filter(id) do
+ Logger.debug("REJECTING #{id}")
+ false
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
index f884962b9..1de5280d9 100644
--- a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
@@ -28,11 +28,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_shortcode], [])
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def history_awareness, do: :manual
- @impl Pleroma.Web.ActivityPub.MRF.Policy
- def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = message)
+ @impl true
+ def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = activity)
when type in ["Create", "Update"] and objtype in Pleroma.Constants.status_object_types() do
with {:ok, object} <-
Updater.do_with_history(object, fn object ->
@@ -42,13 +42,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
Updater.do_with_history(object, fn object ->
{:ok, process_remove(object, :shortcode, config_remove_shortcode())}
end),
- activity <- Map.put(message, "object", object),
+ activity <- Map.put(activity, "object", object),
activity <- maybe_delist(activity) do
{:ok, activity}
end
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def filter(%{"type" => type} = object) when type in Pleroma.Constants.actor_types() do
with object <- process_remove(object, :url, config_remove_url()),
object <- process_remove(object, :shortcode, config_remove_shortcode()) do
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
end
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def filter(%{"type" => "EmojiReact"} = object) do
with {:ok, _} <-
matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do
@@ -67,9 +67,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
end
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
- def filter(message) do
- {:ok, message}
+ @impl true
+ def filter(activity) do
+ {:ok, activity}
end
defp match_string?(string, pattern) when is_binary(pattern) do
@@ -214,7 +214,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
)
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def describe do
mrf_emoji =
Pleroma.Config.get(:mrf_emoji, [])
@@ -226,7 +226,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
{:ok, %{mrf_emoji: mrf_emoji}}
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def config_description do
%{
key: :mrf_emoji,
@@ -239,7 +239,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :remove_url,
type: {:list, :string},
description: """
- A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
+ A list of patterns which result in emoji whose URL matches being removed from the activity. This will apply to statuses, emoji reactions, and user profiles.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -249,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :remove_shortcode,
type: {:list, :string},
description: """
- A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
+ A list of patterns which result in emoji whose shortcode matches being removed from the activity. This will apply to statuses, emoji reactions, and user profiles.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -259,7 +259,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :federated_timeline_removal_url,
type: {:list, :string},
description: """
- A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
+ A list of patterns which result in activity with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -269,7 +269,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
key: :federated_timeline_removal_shortcode,
type: {:list, :string},
description: """
- A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
+ A list of patterns which result in activities with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
diff --git a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
index a148cc1e7..f5983c8a7 100644
--- a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
+++ b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
@@ -29,19 +29,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
def filter_by_summary(_in_reply_to, child), do: child
- def filter(%{"type" => type, "object" => child_object} = object)
- when type in ["Create", "Update"] and is_map(child_object) do
+ def filter(%{"type" => type, "object" => object} = activity)
+ when type in ["Create", "Update"] and is_map(object) do
child =
- child_object["inReplyTo"]
+ object["inReplyTo"]
|> Object.normalize(fetch: false)
- |> filter_by_summary(child_object)
+ |> filter_by_summary(object)
- object = Map.put(object, "object", child)
+ activity = Map.put(activity, "object", child)
- {:ok, object}
+ {:ok, activity}
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex b/lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex
new file mode 100644
index 000000000..2cf22745a
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex
@@ -0,0 +1,53 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.FODirectReply do
+ @moduledoc """
+ FODirectReply alters the scope of replies to activities which are Followers Only to be Direct. The purpose of this policy is to prevent broken threads for followers of the reply author because their response was to a user that they are not also following.
+ """
+
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Visibility
+
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ @impl true
+ def filter(
+ %{
+ "type" => "Create",
+ "to" => to,
+ "object" => %{
+ "actor" => actor,
+ "type" => "Note",
+ "inReplyTo" => in_reply_to
+ }
+ } = activity
+ ) do
+ with true <- is_binary(in_reply_to),
+ %User{follower_address: followers_collection, local: true} <- User.get_by_ap_id(actor),
+ %Object{} = in_reply_to_object <- Object.get_by_ap_id(in_reply_to),
+ "private" <- Visibility.get_visibility(in_reply_to_object) do
+ direct_to = to -- [followers_collection]
+
+ updated_activity =
+ activity
+ |> Map.put("cc", [])
+ |> Map.put("to", direct_to)
+ |> Map.put("directMessage", true)
+ |> put_in(["object", "cc"], [])
+ |> put_in(["object", "to"], direct_to)
+
+ {:ok, updated_activity}
+ else
+ _ -> {:ok, activity}
+ end
+ end
+
+ @impl true
+ def filter(activity), do: {:ok, activity}
+
+ @impl true
+ def describe, do: {:ok, %{}}
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
index 55ea2683c..480a03ef6 100644
--- a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
@@ -11,12 +11,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
require Logger
@impl true
- def filter(message) do
+ def filter(activity) do
with follower_nickname <- Config.get([:mrf_follow_bot, :follower_nickname]),
%User{actor_type: "Service"} = follower <-
User.get_cached_by_nickname(follower_nickname),
- %{"type" => "Create", "object" => %{"type" => "Note"}} <- message do
- try_follow(follower, message)
+ %{"type" => "Create", "object" => %{"type" => "Note"}} <- activity do
+ try_follow(follower, activity)
else
nil ->
Logger.warning(
@@ -24,17 +24,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
account does not exist, or the account is not correctly configured as a bot."
)
- {:ok, message}
+ {:ok, activity}
_ ->
- {:ok, message}
+ {:ok, activity}
end
end
- defp try_follow(follower, message) do
- to = Map.get(message, "to", [])
- cc = Map.get(message, "cc", [])
- actor = [message["actor"]]
+ defp try_follow(follower, activity) do
+ to = Map.get(activity, "to", [])
+ cc = Map.get(activity, "cc", [])
+ actor = [activity["actor"]]
Enum.concat([to, cc, actor])
|> List.flatten()
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
end
end)
- {:ok, message}
+ {:ok, activity}
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
index 8cec8eabe..3b3251dc3 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
@@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
"cc" => cc,
"actor" => actor,
"object" => object
- } = message
+ } = activity
) do
user = User.get_cached_by_ap_id(actor)
isbot = check_if_bot(user)
@@ -36,20 +36,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
|> Map.put("to", to)
|> Map.put("cc", cc)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Map.put("object", object)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mention.ex b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
index 3853489fc..4ea23540d 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mention.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
index 5532093cb..caae365e5 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
@@ -79,18 +79,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
%{
"type" => type,
"object" => %{"type" => "Note", "to" => to, "inReplyTo" => in_reply_to}
- } = object
+ } = activity
)
when type in ["Create", "Update"] and is_list(to) and is_binary(in_reply_to) do
# image-only posts from pleroma apparently reach this MRF without the content field
- content = object["object"]["content"] || ""
+ content = activity["object"]["content"] || ""
# Get the replied-to user for sorting
- replied_to_user = get_replied_to_user(object["object"])
+ replied_to_user = get_replied_to_user(activity["object"])
mention_users =
to
- |> clean_recipients(object)
+ |> clean_recipients(activity)
|> Enum.map(&User.get_cached_by_ap_id/1)
|> Enum.reject(&is_nil/1)
|> sort_replied_user(replied_to_user)
@@ -126,11 +126,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
content
end
- {:ok, put_in(object["object"]["content"], content)}
+ {:ok, put_in(activity["object"]["content"], content)}
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
index fdb9a9dba..72f2274ed 100644
--- a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
alias Pleroma.Object
@moduledoc """
- Reject, TWKN-remove or Set-Sensitive messages with specific hashtags (without the leading #)
+ Reject, TWKN-remove or Set-Sensitive activities with specific hashtags (without the leading #)
Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.
"""
@@ -19,40 +19,40 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
@impl true
def history_awareness, do: :manual
- defp check_reject(message, hashtags) do
+ defp check_reject(activity, hashtags) do
if Enum.any?(Config.get([:mrf_hashtag, :reject]), fn match -> match in hashtags end) do
{:reject, "[HashtagPolicy] Matches with rejected keyword"}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_ftl_removal(%{"to" => to} = message, hashtags) do
+ defp check_ftl_removal(%{"to" => to} = activity, hashtags) do
if Pleroma.Constants.as_public() in to and
Enum.any?(Config.get([:mrf_hashtag, :federated_timeline_removal]), fn match ->
match in hashtags
end) do
to = List.delete(to, Pleroma.Constants.as_public())
- cc = [Pleroma.Constants.as_public() | message["cc"] || []]
+ cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Kernel.put_in(["object", "to"], to)
|> Kernel.put_in(["object", "cc"], cc)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_ftl_removal(message, _hashtags), do: {:ok, message}
+ defp check_ftl_removal(activity, _hashtags), do: {:ok, activity}
- defp check_sensitive(message) do
+ defp check_sensitive(activity) do
{:ok, new_object} =
- Object.Updater.do_with_history(message["object"], fn object ->
+ Object.Updater.do_with_history(activity["object"], fn object ->
hashtags = Object.hashtags(%Object{data: object})
if Enum.any?(Config.get([:mrf_hashtag, :sensitive]), fn match -> match in hashtags end) do
@@ -62,11 +62,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
end
end)
- {:ok, Map.put(message, "object", new_object)}
+ {:ok, Map.put(activity, "object", new_object)}
end
@impl true
- def filter(%{"type" => type, "object" => object} = message) when type in ["Create", "Update"] do
+ def filter(%{"type" => type, "object" => object} = activity)
+ when type in ["Create", "Update"] do
history_items =
with %{"formerRepresentations" => %{"orderedItems" => items}} <- object do
items
@@ -82,23 +83,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
hashtags = Object.hashtags(%Object{data: object}) ++ historical_hashtags
if hashtags != [] do
- with {:ok, message} <- check_reject(message, hashtags),
- {:ok, message} <-
+ with {:ok, activity} <- check_reject(activity, hashtags),
+ {:ok, activity} <-
(if type == "Create" do
- check_ftl_removal(message, hashtags)
+ check_ftl_removal(activity, hashtags)
else
- {:ok, message}
+ {:ok, activity}
end),
- {:ok, message} <- check_sensitive(message) do
- {:ok, message}
+ {:ok, activity} <- check_sensitive(activity) do
+ {:ok, activity}
end
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -120,21 +121,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
%{
key: :reject,
type: {:list, :string},
- description: "A list of hashtags which result in message being rejected.",
+ description: "A list of hashtags which result in the activity being rejected.",
suggestions: ["foo"]
},
%{
key: :federated_timeline_removal,
type: {:list, :string},
description:
- "A list of hashtags which result in message being removed from federated timelines (a.k.a unlisted).",
+ "A list of hashtags which result in the activity being removed from federated timelines (a.k.a unlisted).",
suggestions: ["foo"]
},
%{
key: :sensitive,
type: {:list, :string},
description:
- "A list of hashtags which result in message being set as sensitive (a.k.a NSFW/R-18)",
+ "A list of hashtags which result in the activity being set as sensitive (a.k.a NSFW/R-18)",
suggestions: ["nsfw", "r18"]
}
]
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index 80e235d6e..3a80d0a69 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -7,54 +7,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
require Pleroma.Constants
- @moduledoc "Block messages with too much mentions (configurable)"
+ @moduledoc "Block activities with too much mentions (configurable)"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp delist_message(message, threshold) when threshold > 0 do
- follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
- to = message["to"] || []
- cc = message["cc"] || []
+ defp delist_activity(activity, threshold) when threshold > 0 do
+ follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
+ to = activity["to"] || []
+ cc = activity["cc"] || []
follower_collection? = Enum.member?(to ++ cc, follower_collection)
- message =
- case get_recipient_count(message) do
+ activity =
+ case get_recipient_count(activity) do
{:public, recipients}
when follower_collection? and recipients > threshold ->
- message
+ activity
|> Map.put("to", [follower_collection])
|> Map.put("cc", [Pleroma.Constants.as_public()])
{:public, recipients} when recipients > threshold ->
- message
+ activity
|> Map.put("to", [])
|> Map.put("cc", [Pleroma.Constants.as_public()])
_ ->
- message
+ activity
end
- {:ok, message}
+ {:ok, activity}
end
- defp delist_message(message, _threshold), do: {:ok, message}
+ defp delist_activity(activity, _threshold), do: {:ok, activity}
- defp reject_message(message, threshold) when threshold > 0 do
- with {_, recipients} <- get_recipient_count(message) do
+ defp reject_activity(activity, threshold) when threshold > 0 do
+ with {_, recipients} <- get_recipient_count(activity) do
if recipients > threshold do
{:reject, "[HellthreadPolicy] #{recipients} recipients is over the limit of #{threshold}"}
else
- {:ok, message}
+ {:ok, activity}
end
end
end
- defp reject_message(message, _threshold), do: {:ok, message}
+ defp reject_activity(activity, _threshold), do: {:ok, activity}
- defp get_recipient_count(message) do
- recipients = (message["to"] || []) ++ (message["cc"] || [])
- follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
+ defp get_recipient_count(activity) do
+ recipients = (activity["to"] || []) ++ (activity["cc"] || [])
+ follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
recipients =
@@ -73,7 +73,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
end
@impl true
- def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = message)
+ def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = activity)
when object_type in ~w{Note Article} do
reject_threshold =
Pleroma.Config.get(
@@ -83,16 +83,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
- with {:ok, message} <- reject_message(message, reject_threshold),
- {:ok, message} <- delist_message(message, delist_threshold) do
- {:ok, message}
+ with {:ok, activity} <- reject_activity(activity, reject_threshold),
+ {:ok, activity} <- delist_activity(activity, delist_threshold) do
+ {:ok, activity}
else
e -> e
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe,
@@ -104,13 +104,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
key: :mrf_hellthread,
related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
label: "MRF Hellthread",
- description: "Block messages with excessive user mentions",
+ description: "Block activities with excessive user mentions",
children: [
%{
key: :delist_threshold,
type: :integer,
description:
- "Number of mentioned users after which the message gets removed from timelines and" <>
+ "Number of mentioned users after which the activity gets removed from timelines and" <>
"disables notifications. Set to 0 to disable.",
suggestions: [10]
},
@@ -118,7 +118,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
key: :reject_threshold,
type: :integer,
description:
- "Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",
+ "Number of mentioned users after which the activity gets rejected. Set to 0 to disable.",
suggestions: [20]
}
]
diff --git a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
index b7a01c27c..469d06ef6 100644
--- a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
@@ -48,12 +48,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def history_awareness, do: :auto
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index 729da4e9c..6ba6fd509 100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
alias Pleroma.Web.ActivityPub.MRF.Utils
- @moduledoc "Reject or Word-Replace messages with a keyword or regex"
+ @moduledoc "Reject or Word-Replace activities with a keyword or regex"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|> Enum.join("\n")
end
- defp check_reject(%{"object" => %{} = object} = message) do
+ defp check_reject(%{"object" => %{} = object} = activity) do
with {:ok, _new_object} <-
Pleroma.Object.Updater.do_with_history(object, fn object ->
payload = object_payload(object)
@@ -35,16 +35,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
end) do
{:reject, "[KeywordPolicy] Matches with rejected keyword"}
else
- {:ok, message}
+ {:ok, activity}
end
end) do
- {:ok, message}
+ {:ok, activity}
else
e -> e
end
end
- defp check_ftl_removal(%{"type" => "Create", "to" => to, "object" => %{} = object} = message) do
+ defp check_ftl_removal(%{"type" => "Create", "to" => to, "object" => %{} = object} = activity) do
check_keyword = fn object ->
payload = object_payload(object)
@@ -67,24 +67,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
if Pleroma.Constants.as_public() in to and should_delist?.(object) do
to = List.delete(to, Pleroma.Constants.as_public())
- cc = [Pleroma.Constants.as_public() | message["cc"] || []]
+ cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_ftl_removal(message) do
- {:ok, message}
+ defp check_ftl_removal(activity) do
+ {:ok, activity}
end
- defp check_replace(%{"object" => %{} = object} = message) do
+ defp check_replace(%{"object" => %{} = object} = activity) do
replace_kw = fn object ->
["content", "name", "summary"]
|> Enum.filter(fn field -> Map.has_key?(object, field) && object[field] end)
@@ -103,18 +103,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
{:ok, object} = Pleroma.Object.Updater.do_with_history(object, replace_kw)
- message = Map.put(message, "object", object)
+ activity = Map.put(activity, "object", object)
- {:ok, message}
+ {:ok, activity}
end
@impl true
- def filter(%{"type" => type, "object" => %{"content" => _content}} = message)
+ def filter(%{"type" => type, "object" => %{"content" => _content}} = activity)
when type in ["Create", "Update"] do
- with {:ok, message} <- check_reject(message),
- {:ok, message} <- check_ftl_removal(message),
- {:ok, message} <- check_replace(message) do
- {:ok, message}
+ with {:ok, activity} <- check_reject(activity),
+ {:ok, activity} <- check_ftl_removal(activity),
+ {:ok, activity} <- check_replace(activity) do
+ {:ok, activity}
else
{:reject, nil} -> {:reject, "[KeywordPolicy] "}
{:reject, _} = e -> e
@@ -123,7 +123,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -154,13 +154,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
related_policy: "Pleroma.Web.ActivityPub.MRF.KeywordPolicy",
label: "MRF Keyword",
description:
- "Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
+ "Reject or Word-Replace activities matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
children: [
%{
key: :reject,
type: {:list, :string},
description: """
- A list of patterns which result in message being rejected.
+ A list of patterns which result in the activity being rejected.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
@@ -170,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
key: :federated_timeline_removal,
type: {:list, :string},
description: """
- A list of patterns which result in message being removed from federated timelines (a.k.a unlisted).
+ A list of patterns which result in the activity being removed from federated timelines (a.k.a unlisted).
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
index 0c5b53def..b0d07a6f8 100644
--- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
HTTP.get(url, [], http_client_opts)
end
- defp preload(%{"object" => %{"attachment" => attachments}} = _message) do
+ defp preload(%{"object" => %{"attachment" => attachments}} = _activity) do
Enum.each(attachments, fn
%{"url" => url} when is_list(url) ->
url
@@ -49,15 +49,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
end
@impl true
- def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = message)
+ def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = activity)
when type in ["Create", "Update"] and is_list(attachments) and length(attachments) > 0 do
- preload(message)
+ preload(activity)
- {:ok, message}
+ {:ok, activity}
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
index 8aa4f347f..f7bff121f 100644
--- a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
@@ -3,25 +3,25 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
- @moduledoc "Block messages which mention a user"
+ @moduledoc "Block activities which mention a user"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(%{"type" => "Create"} = message) do
+ def filter(%{"type" => "Create"} = activity) do
reject_actors = Pleroma.Config.get([:mrf_mention, :actors], [])
- recipients = (message["to"] || []) ++ (message["cc"] || [])
+ recipients = (activity["to"] || []) ++ (activity["cc"] || [])
if rejected_mention =
Enum.find(recipients, fn recipient -> Enum.member?(reject_actors, recipient) end) do
{:reject, "[MentionPolicy] Rejected for mention of #{rejected_mention}"}
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
@@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
key: :mrf_mention,
related_policy: "Pleroma.Web.ActivityPub.MRF.MentionPolicy",
label: "MRF Mention",
- description: "Block messages which mention a specific user",
+ description: "Block activities which mention a specific user",
children: [
%{
key: :actors,
diff --git a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
index 12bf4ddd2..08dd39878 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
@@ -9,20 +9,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
alias Pleroma.Web.Endpoint
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
with true <- local?(actor),
- true <- eligible_type?(object),
- true <- note?(object),
- false <- has_attachment?(object),
- true <- only_mentions?(object) do
+ true <- eligible_type?(activity),
+ true <- note?(activity),
+ false <- has_attachment?(activity),
+ true <- only_mentions?(activity) do
{:reject, "[NoEmptyPolicy]"}
else
_ ->
- {:ok, object}
+ {:ok, activity}
end
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
defp local?(actor) do
if actor |> String.starts_with?("#{Endpoint.url()}") do
diff --git a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
index 8840c4fac..64a5872bc 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
@@ -7,8 +7,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(object) do
- {:ok, object}
+ def filter(activity) do
+ {:ok, activity}
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
index f81e9e52a..c6f239a5e 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
@@ -13,15 +13,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
def filter(
%{
"type" => type,
- "object" => %{"content" => content, "attachment" => _} = _child_object
- } = object
+ "object" => %{"content" => content, "attachment" => _} = _object
+ } = activity
)
when type in ["Create", "Update"] and content in [".", "<p>.</p>"] do
- {:ok, put_in(object, ["object", "content"], "")}
+ {:ok, put_in(activity, ["object", "content"], "")}
end
@impl true
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
index 2dfc9a901..91855ef84 100644
--- a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
+++ b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
@@ -12,20 +12,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
def history_awareness, do: :auto
@impl true
- def filter(%{"type" => type, "object" => child_object} = object)
+ def filter(%{"type" => type, "object" => object} = activity)
when type in ["Create", "Update"] do
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
content =
- child_object["content"]
+ object["content"]
|> HTML.filter_tags(scrub_policy)
- object = put_in(object, ["object", "content"], content)
+ activity = put_in(activity, ["object", "content"], content)
- {:ok, object}
+ {:ok, activity}
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex b/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
index 451a212d4..52aaf05aa 100644
--- a/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
@@ -122,52 +122,52 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
end
end
- def check_object_nsfw(%{"object" => %{} = child_object} = object) do
- case check_object_nsfw(child_object) do
- {:sfw, _} -> {:sfw, object}
- {:nsfw, _} -> {:nsfw, object}
+ def check_object_nsfw(%{"object" => %{} = object} = activity) do
+ case check_object_nsfw(object) do
+ {:sfw, _} -> {:sfw, activity}
+ {:nsfw, _} -> {:nsfw, activity}
end
end
def check_object_nsfw(object), do: {:sfw, object}
@impl true
- def filter(object) do
- with {:sfw, object} <- check_object_nsfw(object) do
- {:ok, object}
+ def filter(activity) do
+ with {:sfw, activity} <- check_object_nsfw(activity) do
+ {:ok, activity}
else
- {:nsfw, _data} -> handle_nsfw(object)
+ {:nsfw, _data} -> handle_nsfw(activity)
end
end
- defp handle_nsfw(object) do
+ defp handle_nsfw(activity) do
if Config.get([@policy, :reject]) do
- {:reject, object}
+ {:reject, activity}
else
{:ok,
- object
+ activity
|> maybe_unlist()
|> maybe_mark_sensitive()}
end
end
- defp maybe_unlist(object) do
+ defp maybe_unlist(activity) do
if Config.get([@policy, :unlist]) do
- unlist(object)
+ unlist(activity)
else
- object
+ activity
end
end
- defp maybe_mark_sensitive(object) do
+ defp maybe_mark_sensitive(activity) do
if Config.get([@policy, :mark_sensitive]) do
- mark_sensitive(object)
+ mark_sensitive(activity)
else
- object
+ activity
end
end
- def unlist(%{"to" => to, "cc" => cc, "actor" => actor} = object) do
+ def unlist(%{"to" => to, "cc" => cc, "actor" => actor} = activity) do
with %User{} = user <- User.get_cached_by_ap_id(actor) do
to =
[user.follower_address | to]
@@ -179,7 +179,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|> List.delete(user.follower_address)
|> Enum.uniq()
- object
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
else
@@ -187,14 +187,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
end
end
- def mark_sensitive(%{"object" => child_object} = object) when is_map(child_object) do
- Map.put(object, "object", mark_sensitive(child_object))
+ def mark_sensitive(%{"object" => object} = activity) when is_map(object) do
+ Map.put(activity, "object", mark_sensitive(object))
end
- def mark_sensitive(object) when is_map(object) do
- tags = (object["tag"] || []) ++ ["nsfw"]
+ def mark_sensitive(activity) when is_map(activity) do
+ tags = (activity["tag"] || []) ++ ["nsfw"]
- object
+ activity
|> Map.put("tag", tags)
|> Map.put("sensitive", true)
end
diff --git a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
index df1a6dcbb..34905fc21 100644
--- a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
@@ -11,12 +11,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
@moduledoc "Filter activities depending on their age"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp check_date(%{"object" => %{"published" => published}} = message) do
+ defp check_date(%{"object" => %{"published" => published}} = activity) do
with %DateTime{} = now <- DateTime.utc_now(),
{:ok, %DateTime{} = then, _} <- DateTime.from_iso8601(published),
max_ttl <- Config.get([:mrf_object_age, :threshold]),
{:ttl, false} <- {:ttl, DateTime.diff(now, then) > max_ttl} do
- {:ok, message}
+ {:ok, activity}
else
{:ttl, true} ->
{:reject, nil}
@@ -26,73 +26,73 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
end
end
- defp check_reject(message, actions) do
+ defp check_reject(activity, actions) do
if :reject in actions do
{:reject, "[ObjectAgePolicy]"}
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_delist(message, actions) do
+ defp check_delist(activity, actions) do
if :delist in actions do
- with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
+ with %User{} = user <- User.get_cached_by_ap_id(activity["actor"]) do
to =
- List.delete(message["to"] || [], Pleroma.Constants.as_public()) ++
+ List.delete(activity["to"] || [], Pleroma.Constants.as_public()) ++
[user.follower_address]
cc =
- List.delete(message["cc"] || [], user.follower_address) ++
+ List.delete(activity["cc"] || [], user.follower_address) ++
[Pleroma.Constants.as_public()]
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Kernel.put_in(["object", "to"], to)
|> Kernel.put_in(["object", "cc"], cc)
- {:ok, message}
+ {:ok, activity}
else
_e ->
{:reject, "[ObjectAgePolicy] Unhandled error"}
end
else
- {:ok, message}
+ {:ok, activity}
end
end
- defp check_strip_followers(message, actions) do
+ defp check_strip_followers(activity, actions) do
if :strip_followers in actions do
- with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
- to = List.delete(message["to"] || [], user.follower_address)
- cc = List.delete(message["cc"] || [], user.follower_address)
+ with %User{} = user <- User.get_cached_by_ap_id(activity["actor"]) do
+ to = List.delete(activity["to"] || [], user.follower_address)
+ cc = List.delete(activity["cc"] || [], user.follower_address)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Kernel.put_in(["object", "to"], to)
|> Kernel.put_in(["object", "cc"], cc)
- {:ok, message}
+ {:ok, activity}
else
_e ->
{:reject, "[ObjectAgePolicy] Unhandled error"}
end
else
- {:ok, message}
+ {:ok, activity}
end
end
@impl true
- def filter(%{"type" => "Create", "object" => %{"published" => _}} = message) do
+ def filter(%{"type" => "Create", "object" => %{"published" => _}} = activity) do
with actions <- Config.get([:mrf_object_age, :actions]),
- {:reject, _} <- check_date(message),
- {:ok, message} <- check_reject(message, actions),
- {:ok, message} <- check_delist(message, actions),
- {:ok, message} <- check_strip_followers(message, actions) do
- {:ok, message}
+ {:reject, _} <- check_date(activity),
+ {:ok, activity} <- check_reject(activity, actions),
+ {:ok, activity} <- check_delist(activity, actions),
+ {:ok, activity} <- check_strip_followers(activity, actions) do
+ {:ok, activity}
else
# check_date() is allowed to short-circuit the pipeline
e -> e
@@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
@@ -131,8 +131,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
type: {:list, :atom},
description:
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
- "`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines, additionally for followers-only it degrades to a direct message; " <>
- "`:reject` rejects the message entirely",
+ "`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines, additionally for followers-only it degrades to a direct activity; " <>
+ "`:reject` rejects the activity entirely",
suggestions: [:delist, :strip_followers, :reject]
}
]
diff --git a/lib/pleroma/web/activity_pub/mrf/policy.ex b/lib/pleroma/web/activity_pub/mrf/policy.ex
index 1f34883e7..08bcac08a 100644
--- a/lib/pleroma/web/activity_pub/mrf/policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/policy.ex
@@ -3,7 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.Policy do
- @callback filter(map()) :: {:ok | :reject, map()}
+ @callback filter(Pleroma.Activity.t()) :: {:ok | :reject, Pleroma.Activity.t()}
+ @callback id_filter(String.t()) :: boolean()
@callback describe() :: {:ok | :error, map()}
@callback config_description() :: %{
optional(:children) => [map()],
@@ -13,5 +14,5 @@ defmodule Pleroma.Web.ActivityPub.MRF.Policy do
description: String.t()
}
@callback history_awareness() :: :auto | :manual
- @optional_callbacks config_description: 0, history_awareness: 0
+ @optional_callbacks config_description: 0, history_awareness: 0, id_filter: 1
end
diff --git a/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex b/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
new file mode 100644
index 000000000..b07dc3b56
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
@@ -0,0 +1,60 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.QuietReply do
+ @moduledoc """
+ QuietReply alters the scope of activities from local users when replying by enforcing them to be "Unlisted" or "Quiet Public". This delivers the activity to all the expected recipients and instances, but it will not be published in the Federated / The Whole Known Network timelines. It will still be published to the Home timelines of the user's followers and visible to anyone who opens the thread.
+ """
+ require Pleroma.Constants
+
+ alias Pleroma.User
+
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ @impl true
+ def history_awareness, do: :auto
+
+ @impl true
+ def filter(
+ %{
+ "type" => "Create",
+ "to" => to,
+ "cc" => cc,
+ "object" => %{
+ "actor" => actor,
+ "type" => "Note",
+ "inReplyTo" => in_reply_to
+ }
+ } = activity
+ ) do
+ with true <- is_binary(in_reply_to),
+ false <- match?([], cc),
+ %User{follower_address: followers_collection, local: true} <-
+ User.get_by_ap_id(actor) do
+ updated_to =
+ to
+ |> Kernel.++([followers_collection])
+ |> Kernel.--([Pleroma.Constants.as_public()])
+
+ updated_cc = [Pleroma.Constants.as_public()]
+
+ updated_activity =
+ activity
+ |> Map.put("to", updated_to)
+ |> Map.put("cc", updated_cc)
+ |> put_in(["object", "to"], updated_to)
+ |> put_in(["object", "cc"], updated_cc)
+
+ {:ok, updated_activity}
+ else
+ _ -> {:ok, activity}
+ end
+ end
+
+ @impl true
+ def filter(activity), do: {:ok, activity}
+
+ @impl true
+ def describe, do: {:ok, %{}}
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
index ac353f03f..2a17b6761 100644
--- a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
@@ -10,18 +10,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
require Pleroma.Constants
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
{:ok, Map.put(activity, "object", filter_object(object))}
end
- @impl Pleroma.Web.ActivityPub.MRF.Policy
- def filter(object), do: {:ok, object}
+ @impl true
+ def filter(activity), do: {:ok, activity}
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def describe, do: {:ok, %{}}
- @impl Pleroma.Web.ActivityPub.MRF.Policy
+ @impl true
def history_awareness, do: :auto
defp filter_object(%{"quoteUrl" => quote_url} = object) do
diff --git a/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex b/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
new file mode 100644
index 000000000..fa0610bf1
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
@@ -0,0 +1,118 @@
+defmodule Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy do
+ @moduledoc "Drop remote reports if they don't contain enough information."
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ alias Pleroma.Config
+
+ @impl true
+ def filter(%{"type" => "Flag"} = object) do
+ with {_, false} <- {:local, local?(object)},
+ {:ok, _} <- maybe_reject_all(object),
+ {:ok, _} <- maybe_reject_anonymous(object),
+ {:ok, _} <- maybe_reject_third_party(object),
+ {:ok, _} <- maybe_reject_empty_message(object) do
+ {:ok, object}
+ else
+ {:local, true} -> {:ok, object}
+ {:reject, message} -> {:reject, message}
+ error -> {:reject, error}
+ end
+ end
+
+ def filter(object), do: {:ok, object}
+
+ defp maybe_reject_all(object) do
+ if Config.get([:mrf_remote_report, :reject_all]) do
+ {:reject, "[RemoteReportPolicy] Remote report"}
+ else
+ {:ok, object}
+ end
+ end
+
+ defp maybe_reject_anonymous(%{"actor" => actor} = object) do
+ with true <- Config.get([:mrf_remote_report, :reject_anonymous]),
+ %URI{path: "/actor"} <- URI.parse(actor) do
+ {:reject, "[RemoteReportPolicy] Anonymous: #{actor}"}
+ else
+ _ -> {:ok, object}
+ end
+ end
+
+ defp maybe_reject_third_party(%{"object" => objects} = object) do
+ {_, to} =
+ case objects do
+ [head | tail] when is_binary(head) -> {tail, head}
+ s when is_binary(s) -> {[], s}
+ _ -> {[], ""}
+ end
+
+ with true <- Config.get([:mrf_remote_report, :reject_third_party]),
+ false <- String.starts_with?(to, Pleroma.Web.Endpoint.url()) do
+ {:reject, "[RemoteReportPolicy] Third-party: #{to}"}
+ else
+ _ -> {:ok, object}
+ end
+ end
+
+ defp maybe_reject_empty_message(%{"content" => content} = object)
+ when is_binary(content) and content != "" do
+ {:ok, object}
+ end
+
+ defp maybe_reject_empty_message(object) do
+ if Config.get([:mrf_remote_report, :reject_empty_message]) do
+ {:reject, ["RemoteReportPolicy] No content"]}
+ else
+ {:ok, object}
+ end
+ end
+
+ defp local?(%{"actor" => actor}) do
+ String.starts_with?(actor, Pleroma.Web.Endpoint.url())
+ end
+
+ @impl true
+ def describe do
+ mrf_remote_report =
+ Config.get(:mrf_remote_report)
+ |> Enum.into(%{})
+
+ {:ok, %{mrf_remote_report: mrf_remote_report}}
+ end
+
+ @impl true
+ def config_description do
+ %{
+ key: :mrf_remote_report,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy",
+ label: "MRF Remote Report",
+ description: "Drop remote reports if they don't contain enough information.",
+ children: [
+ %{
+ key: :reject_all,
+ type: :boolean,
+ description: "Reject all remote reports? (this option takes precedence)",
+ suggestions: [false]
+ },
+ %{
+ key: :reject_anonymous,
+ type: :boolean,
+ description: "Reject anonymous remote reports?",
+ suggestions: [true]
+ },
+ %{
+ key: :reject_third_party,
+ type: :boolean,
+ description: "Reject reports on users from third-party instances?",
+ suggestions: [true]
+ },
+ %{
+ key: :reject_empty_message,
+ type: :boolean,
+ description: "Reject remote reports with no message?",
+ suggestions: [true]
+ }
+ ]
+ }
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index d708c99eb..a97e8db7b 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -13,20 +13,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
require Pleroma.Constants
- defp check_accept(%{host: actor_host} = _actor_info, object) do
+ defp check_accept(%{host: actor_host} = _actor_info, activity) do
accepts =
instance_list(:accept)
|> MRF.subdomains_regex()
cond do
- accepts == [] -> {:ok, object}
- actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object}
- MRF.subdomain_match?(accepts, actor_host) -> {:ok, object}
+ accepts == [] -> {:ok, activity}
+ actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, activity}
+ MRF.subdomain_match?(accepts, actor_host) -> {:ok, activity}
true -> {:reject, "[SimplePolicy] host not in accept list"}
end
end
- defp check_reject(%{host: actor_host} = _actor_info, object) do
+ defp check_reject(%{host: actor_host} = _actor_info, activity) do
rejects =
instance_list(:reject)
|> MRF.subdomains_regex()
@@ -34,109 +34,109 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if MRF.subdomain_match?(rejects, actor_host) do
{:reject, "[SimplePolicy] host in reject list"}
else
- {:ok, object}
+ {:ok, activity}
end
end
defp check_media_removal(
%{host: actor_host} = _actor_info,
- %{"type" => type, "object" => %{"attachment" => child_attachment}} = object
+ %{"type" => type, "object" => %{"attachment" => object_attachment}} = activity
)
- when length(child_attachment) > 0 and type in ["Create", "Update"] do
+ when length(object_attachment) > 0 and type in ["Create", "Update"] do
media_removal =
instance_list(:media_removal)
|> MRF.subdomains_regex()
- object =
+ activity =
if MRF.subdomain_match?(media_removal, actor_host) do
- child_object = Map.delete(object["object"], "attachment")
- Map.put(object, "object", child_object)
+ object = Map.delete(activity["object"], "attachment")
+ Map.put(activity, "object", object)
else
- object
+ activity
end
- {:ok, object}
+ {:ok, activity}
end
- defp check_media_removal(_actor_info, object), do: {:ok, object}
+ defp check_media_removal(_actor_info, activity), do: {:ok, activity}
defp check_media_nsfw(
%{host: actor_host} = _actor_info,
%{
"type" => type,
- "object" => %{} = _child_object
- } = object
+ "object" => %{} = _object
+ } = activity
)
when type in ["Create", "Update"] do
media_nsfw =
instance_list(:media_nsfw)
|> MRF.subdomains_regex()
- object =
+ activity =
if MRF.subdomain_match?(media_nsfw, actor_host) do
- Kernel.put_in(object, ["object", "sensitive"], true)
+ Kernel.put_in(activity, ["object", "sensitive"], true)
else
- object
+ activity
end
- {:ok, object}
+ {:ok, activity}
end
- defp check_media_nsfw(_actor_info, object), do: {:ok, object}
+ defp check_media_nsfw(_actor_info, activity), do: {:ok, activity}
- defp check_ftl_removal(%{host: actor_host} = _actor_info, object) do
+ defp check_ftl_removal(%{host: actor_host} = _actor_info, activity) do
timeline_removal =
instance_list(:federated_timeline_removal)
|> MRF.subdomains_regex()
- object =
+ activity =
with true <- MRF.subdomain_match?(timeline_removal, actor_host),
- user <- User.get_cached_by_ap_id(object["actor"]),
- true <- Pleroma.Constants.as_public() in object["to"] do
- to = List.delete(object["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
+ user <- User.get_cached_by_ap_id(activity["actor"]),
+ true <- Pleroma.Constants.as_public() in activity["to"] do
+ to = List.delete(activity["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
- cc = List.delete(object["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
+ cc = List.delete(activity["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
- object
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
else
- _ -> object
+ _ -> activity
end
- {:ok, object}
+ {:ok, activity}
end
defp intersection(list1, list2) do
list1 -- list1 -- list2
end
- defp check_followers_only(%{host: actor_host} = _actor_info, object) do
+ defp check_followers_only(%{host: actor_host} = _actor_info, activity) do
followers_only =
instance_list(:followers_only)
|> MRF.subdomains_regex()
- object =
+ activity =
with true <- MRF.subdomain_match?(followers_only, actor_host),
- user <- User.get_cached_by_ap_id(object["actor"]) do
+ user <- User.get_cached_by_ap_id(activity["actor"]) do
# Don't use Map.get/3 intentionally, these must not be nil
- fixed_to = object["to"] || []
- fixed_cc = object["cc"] || []
+ fixed_to = activity["to"] || []
+ fixed_cc = activity["cc"] || []
to = FollowingRelationship.followers_ap_ids(user, fixed_to)
cc = FollowingRelationship.followers_ap_ids(user, fixed_cc)
- object
+ activity
|> Map.put("to", intersection([user.follower_address | to], fixed_to))
|> Map.put("cc", intersection([user.follower_address | cc], fixed_cc))
else
- _ -> object
+ _ -> activity
end
- {:ok, object}
+ {:ok, activity}
end
- defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = object) do
+ defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = activity) do
report_removal =
instance_list(:report_removal)
|> MRF.subdomains_regex()
@@ -144,39 +144,39 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if MRF.subdomain_match?(report_removal, actor_host) do
{:reject, "[SimplePolicy] host in report_removal list"}
else
- {:ok, object}
+ {:ok, activity}
end
end
- defp check_report_removal(_actor_info, object), do: {:ok, object}
+ defp check_report_removal(_actor_info, activity), do: {:ok, activity}
- defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do
+ defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = activity) do
avatar_removal =
instance_list(:avatar_removal)
|> MRF.subdomains_regex()
if MRF.subdomain_match?(avatar_removal, actor_host) do
- {:ok, Map.delete(object, "icon")}
+ {:ok, Map.delete(activity, "icon")}
else
- {:ok, object}
+ {:ok, activity}
end
end
- defp check_avatar_removal(_actor_info, object), do: {:ok, object}
+ defp check_avatar_removal(_actor_info, activity), do: {:ok, activity}
- defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do
+ defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = activity) do
banner_removal =
instance_list(:banner_removal)
|> MRF.subdomains_regex()
if MRF.subdomain_match?(banner_removal, actor_host) do
- {:ok, Map.delete(object, "image")}
+ {:ok, Map.delete(activity, "image")}
else
- {:ok, object}
+ {:ok, activity}
end
end
- defp check_banner_removal(_actor_info, object), do: {:ok, object}
+ defp check_banner_removal(_actor_info, activity), do: {:ok, activity}
defp check_object(%{"object" => object} = activity) do
with {:ok, _object} <- filter(object) do
@@ -184,7 +184,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
end
end
- defp check_object(object), do: {:ok, object}
+ defp check_object(activity), do: {:ok, activity}
defp instance_list(config_key) do
Config.get([:mrf_simple, config_key])
@@ -192,7 +192,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
end
@impl true
- def filter(%{"type" => "Delete", "actor" => actor} = object) do
+ def id_filter(id) do
+ host_info = URI.parse(id)
+
+ with {:ok, _} <- check_accept(host_info, %{}),
+ {:ok, _} <- check_reject(host_info, %{}) do
+ true
+ else
+ _ -> false
+ end
+ end
+
+ @impl true
+ def filter(%{"type" => "Delete", "actor" => actor} = activity) do
%{host: actor_host} = URI.parse(actor)
reject_deletes =
@@ -202,54 +214,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
if MRF.subdomain_match?(reject_deletes, actor_host) do
{:reject, "[SimplePolicy] host in reject_deletes list"}
else
- {:ok, object}
+ {:ok, activity}
end
end
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
actor_info = URI.parse(actor)
- with {:ok, object} <- check_accept(actor_info, object),
- {:ok, object} <- check_reject(actor_info, object),
- {:ok, object} <- check_media_removal(actor_info, object),
- {:ok, object} <- check_media_nsfw(actor_info, object),
- {:ok, object} <- check_ftl_removal(actor_info, object),
- {:ok, object} <- check_followers_only(actor_info, object),
- {:ok, object} <- check_report_removal(actor_info, object),
- {:ok, object} <- check_object(object) do
- {:ok, object}
+ with {:ok, activity} <- check_accept(actor_info, activity),
+ {:ok, activity} <- check_reject(actor_info, activity),
+ {:ok, activity} <- check_media_removal(actor_info, activity),
+ {:ok, activity} <- check_media_nsfw(actor_info, activity),
+ {:ok, activity} <- check_ftl_removal(actor_info, activity),
+ {:ok, activity} <- check_followers_only(actor_info, activity),
+ {:ok, activity} <- check_report_removal(actor_info, activity),
+ {:ok, activity} <- check_object(activity) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(%{"id" => actor, "type" => obj_type} = object)
- when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
+ def filter(%{"id" => actor, "type" => actor_type} = activity)
+ when actor_type in ["Application", "Group", "Organization", "Person", "Service"] do
actor_info = URI.parse(actor)
- with {:ok, object} <- check_accept(actor_info, object),
- {:ok, object} <- check_reject(actor_info, object),
- {:ok, object} <- check_avatar_removal(actor_info, object),
- {:ok, object} <- check_banner_removal(actor_info, object) do
- {:ok, object}
+ with {:ok, activity} <- check_accept(actor_info, activity),
+ {:ok, activity} <- check_reject(actor_info, activity),
+ {:ok, activity} <- check_avatar_removal(actor_info, activity),
+ {:ok, activity} <- check_banner_removal(actor_info, activity) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(object) when is_binary(object) do
- uri = URI.parse(object)
+ def filter(activity) when is_binary(activity) do
+ uri = URI.parse(activity)
- with {:ok, object} <- check_accept(uri, object),
- {:ok, object} <- check_reject(uri, object) do
- {:ok, object}
+ with {:ok, activity} <- check_accept(uri, activity),
+ {:ok, activity} <- check_reject(uri, activity) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
index fa6b595ea..6edfb124e 100644
--- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
end
@impl true
- def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = message) do
+ def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = activity) do
host = URI.parse(actor).host
if host != Pleroma.Web.Endpoint.host() and accept_host?(host) do
@@ -97,10 +97,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
end
end
- {:ok, message}
+ {:ok, activity}
end
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
@spec config_description :: %{
diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
index fdb9e5176..97acca7e8 100644
--- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
@@ -20,20 +20,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
end
@impl true
- def filter(%{"actor" => actor} = message) do
+ def filter(%{"actor" => actor} = activity) do
with {:ok, match, subchain} <- lookup_subchain(actor) do
Logger.debug(
"[SubchainPolicy] Matched #{actor} against #{inspect(match)} with subchain #{inspect(subchain)}"
)
- MRF.filter(subchain, message)
+ MRF.filter(subchain, activity)
else
- _e -> {:ok, message}
+ _e -> {:ok, activity}
end
end
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
@@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
related_policy: "Pleroma.Web.ActivityPub.MRF.SubchainPolicy",
label: "MRF Subchain",
description:
- "This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
+ "This policy processes activities through an alternate pipeline when a given activity matches certain criteria." <>
" All criteria are configured as a map of regular expressions to lists of policy modules.",
children: [
%{
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index 73760ca8f..c236a5a99 100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -28,25 +28,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
"mrf_tag:media-force-nsfw",
%{
"type" => type,
- "object" => %{"attachment" => child_attachment}
- } = message
+ "object" => %{"attachment" => object_attachment}
+ } = activity
)
- when length(child_attachment) > 0 and type in ["Create", "Update"] do
- {:ok, Kernel.put_in(message, ["object", "sensitive"], true)}
+ when length(object_attachment) > 0 and type in ["Create", "Update"] do
+ {:ok, Kernel.put_in(activity, ["object", "sensitive"], true)}
end
defp process_tag(
"mrf_tag:media-strip",
%{
"type" => type,
- "object" => %{"attachment" => child_attachment} = object
- } = message
+ "object" => %{"attachment" => object_attachment} = object
+ } = activity
)
- when length(child_attachment) > 0 and type in ["Create", "Update"] do
+ when length(object_attachment) > 0 and type in ["Create", "Update"] do
object = Map.delete(object, "attachment")
- message = Map.put(message, "object", object)
+ activity = Map.put(activity, "object", object)
- {:ok, message}
+ {:ok, activity}
end
defp process_tag(
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
"cc" => cc,
"actor" => actor,
"object" => object
- } = message
+ } = activity
) do
user = User.get_cached_by_ap_id(actor)
@@ -70,15 +70,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|> Map.put("to", to)
|> Map.put("cc", cc)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Map.put("object", object)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
@@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
"cc" => cc,
"actor" => actor,
"object" => object
- } = message
+ } = activity
) do
user = User.get_cached_by_ap_id(actor)
@@ -104,26 +104,26 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|> Map.put("to", to)
|> Map.put("cc", cc)
- message =
- message
+ activity =
+ activity
|> Map.put("to", to)
|> Map.put("cc", cc)
|> Map.put("object", object)
- {:ok, message}
+ {:ok, activity}
else
- {:ok, message}
+ {:ok, activity}
end
end
defp process_tag(
"mrf_tag:disable-remote-subscription",
- %{"type" => "Follow", "actor" => actor} = message
+ %{"type" => "Follow", "actor" => actor} = activity
) do
user = User.get_cached_by_ap_id(actor)
if user.local == true do
- {:ok, message}
+ {:ok, activity}
else
{:reject,
"[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-remote-subscription"}
@@ -133,14 +133,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow", "actor" => actor}),
do: {:reject, "[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-any-subscription"}
- defp process_tag(_, message), do: {:ok, message}
+ defp process_tag(_, activity), do: {:ok, activity}
- def filter_message(actor, message) do
+ def filter_activity(actor, activity) do
User.get_cached_by_ap_id(actor)
|> get_tags()
- |> Enum.reduce({:ok, message}, fn
- tag, {:ok, message} ->
- process_tag(tag, message)
+ |> Enum.reduce({:ok, activity}, fn
+ tag, {:ok, activity} ->
+ process_tag(tag, activity)
_, error ->
error
@@ -148,15 +148,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
end
@impl true
- def filter(%{"object" => target_actor, "type" => "Follow"} = message),
- do: filter_message(target_actor, message)
+ def filter(%{"object" => target_actor, "type" => "Follow"} = activity),
+ do: filter_activity(target_actor, activity)
@impl true
- def filter(%{"actor" => actor, "type" => type} = message) when type in ["Create", "Update"],
- do: filter_message(actor, message)
+ def filter(%{"actor" => actor, "type" => type} = activity) when type in ["Create", "Update"],
+ do: filter_activity(actor, activity)
@impl true
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
index e14047d4e..10cc0e09d 100644
--- a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
@@ -8,18 +8,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
@moduledoc "Accept-list of users from specified instances"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp filter_by_list(object, []), do: {:ok, object}
+ defp filter_by_list(activity, []), do: {:ok, activity}
- defp filter_by_list(%{"actor" => actor} = object, allow_list) do
+ defp filter_by_list(%{"actor" => actor} = activity, allow_list) do
if actor in allow_list do
- {:ok, object}
+ {:ok, activity}
else
{:reject, "[UserAllowListPolicy] #{actor} not in the list"}
end
end
@impl true
- def filter(%{"actor" => actor} = object) do
+ def filter(%{"actor" => actor} = activity) do
actor_info = URI.parse(actor)
allow_list =
@@ -28,10 +28,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
[]
)
- filter_by_list(object, allow_list)
+ filter_by_list(activity, allow_list)
end
- def filter(object), do: {:ok, object}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe do
diff --git a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
index 1c114558e..5671e4cf3 100644
--- a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
@@ -3,38 +3,38 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
- @moduledoc "Filter messages which belong to certain activity vocabularies"
+ @moduledoc "Filter activities which belong to certain activity vocabularies"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(%{"type" => "Undo", "object" => child_message} = message) do
- with {:ok, _} <- filter(child_message) do
- {:ok, message}
+ def filter(%{"type" => "Undo", "object" => object} = activity) do
+ with {:ok, _} <- filter(object) do
+ {:ok, activity}
else
{:reject, _} = e -> e
end
end
- def filter(%{"type" => message_type} = message) do
+ def filter(%{"type" => activity_type} = activity) do
with accepted_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :accept]),
rejected_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :reject]),
{_, true} <-
{:accepted,
- Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, message_type)},
+ Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, activity_type)},
{_, false} <-
{:rejected,
- length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, message_type)},
- {:ok, _} <- filter(message["object"]) do
- {:ok, message}
+ length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, activity_type)},
+ {:ok, _} <- filter(activity["object"]) do
+ {:ok, activity}
else
{:reject, _} = e -> e
- {:accepted, _} -> {:reject, "[VocabularyPolicy] #{message_type} not in accept list"}
- {:rejected, _} -> {:reject, "[VocabularyPolicy] #{message_type} in reject list"}
+ {:accepted, _} -> {:reject, "[VocabularyPolicy] #{activity_type} not in accept list"}
+ {:rejected, _} -> {:reject, "[VocabularyPolicy] #{activity_type} in reject list"}
end
end
- def filter(message), do: {:ok, message}
+ def filter(activity), do: {:ok, activity}
@impl true
def describe,
@@ -46,20 +46,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
key: :mrf_vocabulary,
related_policy: "Pleroma.Web.ActivityPub.MRF.VocabularyPolicy",
label: "MRF Vocabulary",
- description: "Filter messages which belong to certain activity vocabularies",
+ description: "Filter activities which belong to certain activity vocabularies",
children: [
%{
key: :accept,
type: {:list, :string},
description:
- "A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
+ "A list of ActivityStreams terms to accept. If empty, all supported activities are accepted.",
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
},
%{
key: :reject,
type: {:list, :string},
description:
- "A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
+ "A list of ActivityStreams terms to reject. If empty, no activities are rejected.",
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
}
]
diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex
index b3043b93a..35774d410 100644
--- a/lib/pleroma/web/activity_pub/object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validator.ex
@@ -11,6 +11,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating
+ import Pleroma.Constants, only: [activity_types: 0, object_types: 0]
+
alias Pleroma.Activity
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object
@@ -38,6 +40,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@impl true
def validate(object, meta)
+ # This overload works together with the InboxGuardPlug
+ # and ensures that we are not accepting any activity type
+ # that cannot pass InboxGuardPlug.
+ # If we want to support any more activity types, make sure to
+ # add it in Pleroma.Constants's activity_types or object_types,
+ # and, if applicable, allowed_activity_types_from_strangers.
+ def validate(%{"type" => type}, _meta)
+ when type not in activity_types() and type not in object_types(),
+ do: {:error, :not_allowed_object_type}
+
def validate(%{"type" => "Block"} = block_activity, meta) do
with {:ok, block_activity} <-
block_activity
diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
index d611da051..03ab83347 100644
--- a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do
defp validate_data(cng) do
cng
- |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_required([:id, :type, :actor, :to, :object])
|> validate_inclusion(:type, ["Accept", "Reject"])
|> validate_actor_presence()
|> validate_object_presence(allowed_types: ["Follow"])
diff --git a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
index 0de87a27e..98340545c 100644
--- a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do
defp validate_data(cng) do
cng
- |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_required([:id, :type, :actor, :to, :object])
|> validate_inclusion(:type, ["Block"])
|> CommonValidations.validate_actor_presence()
|> CommonValidations.validate_actor_presence(field_name: :object)
diff --git a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
index b3ca5b691..e4e97bf72 100644
--- a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator do
defp validate_data(cng) do
cng
- |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_required([:id, :type, :actor, :to, :object])
|> validate_inclusion(:type, ["Follow"])
|> validate_inclusion(:state, ~w{pending reject accept})
|> validate_actor_presence()
diff --git a/lib/pleroma/web/activity_pub/pipeline.ex b/lib/pleroma/web/activity_pub/pipeline.ex
index 7f11a4d67..fc36935d5 100644
--- a/lib/pleroma/web/activity_pub/pipeline.ex
+++ b/lib/pleroma/web/activity_pub/pipeline.ex
@@ -22,22 +22,27 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
defp activity_pub, do: Config.get([:pipeline, :activity_pub], ActivityPub)
defp config, do: Config.get([:pipeline, :config], Config)
- @spec common_pipeline(map(), keyword()) ::
- {:ok, Activity.t() | Object.t(), keyword()} | {:error | :reject, any()}
+ @type results :: {:ok, Activity.t() | Object.t(), keyword()}
+ @type errors :: {:error | :reject, any()}
+
+ # The Repo.transaction will wrap the result in an {:ok, _}
+ # and only returns an {:error, _} if the error encountered was related
+ # to the SQL transaction
+ @spec common_pipeline(map(), keyword()) :: results() | errors()
def common_pipeline(object, meta) do
case Repo.transaction(fn -> do_common_pipeline(object, meta) end, Utils.query_timeout()) do
{:ok, {:ok, activity, meta}} ->
side_effects().handle_after_transaction(meta)
{:ok, activity, meta}
- {:ok, value} ->
- value
+ {:ok, {:error, _} = error} ->
+ error
+
+ {:ok, {:reject, _} = error} ->
+ error
{:error, e} ->
{:error, e}
-
- {:reject, e} ->
- {:reject, e}
end
end
diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex
index e63b8ff1f..0de3a0d43 100644
--- a/lib/pleroma/web/activity_pub/publisher.ex
+++ b/lib/pleroma/web/activity_pub/publisher.ex
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Publisher.Prepared
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Workers.PublisherWorker
@@ -30,11 +31,11 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
"""
@spec enqueue_one(map(), Keyword.t()) :: {:ok, %Oban.Job{}}
def enqueue_one(%{} = params, worker_args \\ []) do
- PublisherWorker.enqueue(
- "publish_one",
- %{"params" => params},
+ PublisherWorker.new(
+ %{"op" => "publish_one", "params" => params},
worker_args
)
+ |> Oban.insert()
end
@doc """
@@ -76,14 +77,13 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
end
@doc """
- Publish a single message to a peer. Takes a struct with the following
- parameters set:
-
+ Prepare an activity for publishing from an Oban job
* `inbox`: the inbox to publish to
* `activity_id`: the internal activity id
* `cc`: the cc recipients relevant to this inbox (optional)
"""
- def publish_one(%{inbox: inbox, activity_id: activity_id} = params) do
+ @spec prepare_one(map()) :: Prepared.t()
+ def prepare_one(%{inbox: inbox, activity_id: activity_id} = params) do
activity = Activity.get_by_id_with_user_actor(activity_id)
actor = activity.user_actor
@@ -93,7 +93,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
- cc = Map.get(params, :cc)
+ cc = Map.get(params, :cc, [])
json =
data
@@ -113,27 +113,54 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
date: date
})
+ %Prepared{
+ activity_id: activity_id,
+ json: json,
+ date: date,
+ signature: signature,
+ digest: digest,
+ inbox: inbox,
+ unreachable_since: params[:unreachable_since]
+ }
+ end
+
+ @doc """
+ Publish a single message to a peer. Takes a struct with the following
+ parameters set:
+ * `activity_id`: the activity id
+ * `json`: the json payload
+ * `date`: the signed date from Pleroma.Signature.signed_date()
+ * `signature`: the signature from Pleroma.Signature.sign/2
+ * `digest`: base64 encoded the hash of the json payload prefixed with "SHA-256="
+ * `inbox`: the inbox URI of this delivery
+ * `unreachable_since`: timestamp the instance was marked unreachable
+
+ """
+ def publish_one(%Prepared{} = p) do
with {:ok, %{status: code}} = result when code in 200..299 <-
HTTP.post(
- inbox,
- json,
+ p.inbox,
+ p.json,
[
{"Content-Type", "application/activity+json"},
- {"Date", date},
- {"signature", signature},
- {"digest", digest}
+ {"Date", p.date},
+ {"signature", p.signature},
+ {"digest", p.digest}
]
) do
- if not Map.has_key?(params, :unreachable_since) || params[:unreachable_since] do
- Instances.set_reachable(inbox)
+ if not is_nil(p.unreachable_since) do
+ Instances.set_reachable(p.inbox)
end
result
else
{_post_result, %{status: code} = response} = e ->
- unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
- Logger.metadata(activity: activity_id, inbox: inbox, status: code)
- Logger.error("Publisher failed to inbox #{inbox} with status #{code}")
+ if is_nil(p.unreachable_since) do
+ Instances.set_unreachable(p.inbox)
+ end
+
+ Logger.metadata(activity: p.activity_id, inbox: p.inbox, status: code)
+ Logger.error("Publisher failed to inbox #{p.inbox} with status #{code}")
case response do
%{status: 400} -> {:cancel, :bad_request}
@@ -152,9 +179,12 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
connection_pool_snooze()
e ->
- unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
- Logger.metadata(activity: activity_id, inbox: inbox)
- Logger.error("Publisher failed to inbox #{inbox} #{inspect(e)}")
+ if is_nil(p.unreachable_since) do
+ Instances.set_unreachable(p.inbox)
+ end
+
+ Logger.metadata(activity: p.activity_id, inbox: p.inbox)
+ Logger.error("Publisher failed to inbox #{p.inbox} #{inspect(e)}")
{:error, e}
end
end
diff --git a/lib/pleroma/web/activity_pub/publisher/prepared.ex b/lib/pleroma/web/activity_pub/publisher/prepared.ex
new file mode 100644
index 000000000..ddd8167e1
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/publisher/prepared.ex
@@ -0,0 +1,8 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Publisher.Prepared do
+ @type t :: %__MODULE__{}
+ defstruct [:activity_id, :json, :date, :signature, :digest, :inbox, :unreachable_since]
+end
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index cc1c7a0af..d6d403671 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -223,10 +223,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
if Pleroma.Web.Federator.allowed_thread_distance?(reply_depth) and
object.data["replies"] != nil do
for reply_id <- object.data["replies"] do
- Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
+ Pleroma.Workers.RemoteFetcherWorker.new(%{
+ "op" => "fetch_remote",
"id" => reply_id,
"depth" => reply_depth
})
+ |> Oban.insert()
end
end
@@ -410,10 +412,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:ok, expires_at} =
Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime.cast(meta[:expires_at])
- Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
- activity_id: meta[:activity_id],
- expires_at: expires_at
- })
+ Pleroma.Workers.PurgeExpiredActivity.enqueue(
+ %{
+ activity_id: meta[:activity_id]
+ },
+ scheduled_at: expires_at
+ )
end
{:ok, object, meta}
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 937e4fd67..cd485ed64 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -129,8 +129,22 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"vcard:bday" => birthday,
"webfinger" => "acct:#{User.full_nickname(user)}"
}
- |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
- |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
+ |> Map.merge(
+ maybe_make_image(
+ &User.avatar_url/2,
+ User.image_description(user.avatar, nil),
+ "icon",
+ user
+ )
+ )
+ |> Map.merge(
+ maybe_make_image(
+ &User.banner_url/2,
+ User.image_description(user.banner, nil),
+ "image",
+ user
+ )
+ )
|> Map.merge(Utils.make_json_ld_header())
end
@@ -305,16 +319,24 @@ defmodule Pleroma.Web.ActivityPub.UserView do
end
end
- defp maybe_make_image(func, key, user) do
+ defp maybe_make_image(func, description, key, user) do
if image = func.(user, no_default: true) do
%{
- key => %{
- "type" => "Image",
- "url" => image
- }
+ key =>
+ %{
+ "type" => "Image",
+ "url" => image
+ }
+ |> maybe_put_description(description)
}
else
%{}
end
end
+
+ defp maybe_put_description(map, description) when is_binary(description) do
+ Map.put(map, "name", description)
+ end
+
+ defp maybe_put_description(map, _description), do: map
end