mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2025-04-23 21:39:18 -04:00
Merge branch 'improve-mrf-returns' into 'develop'
Draft: Improve MRF contract See merge request pleroma/pleroma!4238
This commit is contained in:
commit
7779620d13
38 changed files with 358 additions and 235 deletions
|
@ -53,6 +53,8 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
|
||||
@required_description_keys [:key, :related_policy]
|
||||
|
||||
@success_types [:ok, :pass, :filter]
|
||||
|
||||
def filter_one(policy, message) do
|
||||
Code.ensure_loaded(policy)
|
||||
|
||||
|
@ -69,7 +71,8 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
else
|
||||
main_result = policy.filter(message)
|
||||
|
||||
with {_, {:ok, main_message}} <- {:main, main_result},
|
||||
with {_, {result_type, main_message}} when result_type in @success_types <-
|
||||
{:main, main_result},
|
||||
{_,
|
||||
%{
|
||||
"formerRepresentations" => %{
|
||||
|
@ -82,8 +85,9 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
object["formerRepresentations"],
|
||||
object,
|
||||
fn item ->
|
||||
with {:ok, filtered} <- policy.filter(Map.put(message, "object", item)) do
|
||||
{:ok, filtered["object"]}
|
||||
with {result_type, filtered} when result_type in @success_types <-
|
||||
policy.filter(Map.put(message, "object", item)) do
|
||||
{:filter, filtered["object"]}
|
||||
else
|
||||
e -> e
|
||||
end
|
||||
|
@ -114,7 +118,8 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
ap_id = message["object"]
|
||||
|
||||
if object && ap_id do
|
||||
with {:ok, message} <- filter(Map.put(message, "object", object)) do
|
||||
with {type, message} when type in @success_types <-
|
||||
filter(Map.put(message, "object", object)) do
|
||||
meta = Keyword.put(meta, :object_data, message["object"])
|
||||
{:ok, Map.put(message, "object", ap_id), meta}
|
||||
else
|
||||
|
|
|
@ -8,14 +8,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(activity) do
|
||||
activity =
|
||||
if note?(activity) and local?(activity) do
|
||||
maybe_add_expiration(activity)
|
||||
else
|
||||
activity
|
||||
end
|
||||
|
||||
{:ok, activity}
|
||||
if note?(activity) and local?(activity) do
|
||||
maybe_add_expiration(activity)
|
||||
else
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
@ -35,9 +32,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do
|
|||
|
||||
with %{"expires_at" => existing_expires_at} <- activity,
|
||||
:lt <- DateTime.compare(existing_expires_at, expires_at) do
|
||||
activity
|
||||
{:pass, activity}
|
||||
else
|
||||
_ -> Map.put(activity, "expires_at", expires_at)
|
||||
_ ->
|
||||
{:filter, Map.put(activity, "expires_at", expires_at)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -69,14 +69,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
|
|||
score = determine_if_followbot(actor)
|
||||
|
||||
if score < 0.8 || bot_allowed?(activity, actor) do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
else
|
||||
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
|
||||
reason = "Scored #{actor_id} as #{score}"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -7,8 +7,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
|
|||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
require Logger
|
||||
|
||||
@impl true
|
||||
def history_awareness, do: :auto
|
||||
|
||||
|
@ -33,27 +31,32 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy 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, activity}
|
||||
{:pass, activity}
|
||||
else
|
||||
{:ok, %User{local: true}} ->
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
|
||||
{:contains_links, false} ->
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
|
||||
{:old_user, false} ->
|
||||
{:reject, "[AntiLinkSpamPolicy] User has no posts nor followers"}
|
||||
reason = "User has no posts nor followers"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
|
||||
{:error, _} ->
|
||||
{:reject, "[AntiLinkSpamPolicy] Failed to get or fetch user by ap_id"}
|
||||
reason = "Failed to get or fetch user by ap_id"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
|
||||
e ->
|
||||
{:reject, "[AntiLinkSpamPolicy] Unhandled error #{inspect(e)}"}
|
||||
reason = "Unhandled error"
|
||||
{:reject, %{activity: activity, reason: reason, error: e}}
|
||||
end
|
||||
end
|
||||
|
||||
# in all other cases, pass through
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -60,27 +60,32 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
|
|||
with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
|
||||
{:has_mentions, true} <- {:has_mentions, object_has_recipients?(activity)},
|
||||
{:good_reputation, true} <- {:good_reputation, good_reputation?(u)} do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
else
|
||||
{:ok, %User{local: true}} ->
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
|
||||
{:has_mentions, false} ->
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
|
||||
{:good_reputation, false} ->
|
||||
{:reject, "[AntiMentionSpamPolicy] User rejected"}
|
||||
reason = "Bad reputation"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
|
||||
{:error, _} ->
|
||||
{:reject, "[AntiMentionSpamPolicy] Failed to get or fetch user by ap_id"}
|
||||
reason = "Failed to get or fetch user by ap_id"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
|
||||
e ->
|
||||
{:reject, "[AntiMentionSpamPolicy] Unhandled error #{inspect(e)}"}
|
||||
reason = "Unhandled error"
|
||||
{:reject, %{activity: activity, reason: reason, error: e}}
|
||||
end
|
||||
end
|
||||
|
||||
# in all other cases, pass through
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -32,8 +32,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
|
||||
alias Pleroma.Config
|
||||
|
||||
require Logger
|
||||
|
||||
@query_retries 1
|
||||
@query_timeout 500
|
||||
|
||||
|
@ -42,14 +40,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
actor_info = URI.parse(actor)
|
||||
|
||||
with {:ok, activity} <- check_rbl(actor_info, activity) do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
else
|
||||
_ -> {:reject, "[DNSRBLPolicy]"}
|
||||
{:error, reason} ->
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
@ -102,19 +103,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
if Enum.empty?(rbl_response) do
|
||||
{:ok, activity}
|
||||
else
|
||||
Task.start(fn ->
|
||||
reason =
|
||||
case rblquery(query, :txt) do
|
||||
[[result]] -> result
|
||||
_ -> "undefined"
|
||||
end
|
||||
reason =
|
||||
case rblquery(query, :txt) do
|
||||
[[result]] -> to_string(result)
|
||||
_ -> "undefined"
|
||||
end
|
||||
|
||||
Logger.warning(
|
||||
"DNSRBL Rejected activity from #{actor_host} for reason: #{inspect(reason)}"
|
||||
)
|
||||
end)
|
||||
|
||||
:error
|
||||
{:error, reason}
|
||||
end
|
||||
else
|
||||
_ -> {:ok, activity}
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
|
||||
require Logger
|
||||
@moduledoc "Drop and log everything received"
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(activity) do
|
||||
Logger.debug("REJECTING #{inspect(activity)}")
|
||||
{:reject, activity}
|
||||
{:reject, %{activity: activity}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -44,7 +44,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
end),
|
||||
activity <- Map.put(activity, "object", object),
|
||||
activity <- maybe_delist(activity) do
|
||||
{:ok, activity}
|
||||
{:filter, activity}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
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
|
||||
{:ok, object}
|
||||
{:filter, object}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -60,16 +60,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
def filter(%{"type" => "EmojiReact"} = object) do
|
||||
with {:ok, _} <-
|
||||
matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do
|
||||
{:ok, object}
|
||||
{:filter, object}
|
||||
else
|
||||
_ ->
|
||||
{:reject, "[EmojiPolicy] Rejected for having disallowed emoji"}
|
||||
reason = "Has disallowed emoji"
|
||||
{:reject, %{activity: object, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity) do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
defp match_string?(string, pattern) when is_binary(pattern) do
|
||||
|
|
|
@ -38,10 +38,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
|
|||
|
||||
activity = Map.put(activity, "object", child)
|
||||
|
||||
{:ok, activity}
|
||||
if match?(^child, object["inReplyTo"]) do
|
||||
{:pass, activity}
|
||||
else
|
||||
{:filter, activity}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
@ -39,14 +39,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.FODirectReply do
|
|||
|> put_in(["object", "cc"], [])
|
||||
|> put_in(["object", "to"], direct_to)
|
||||
|
||||
{:ok, updated_activity}
|
||||
{:filter, updated_activity}
|
||||
else
|
||||
_ -> {:ok, activity}
|
||||
_ ->
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -19,15 +19,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
|
|||
try_follow(follower, activity)
|
||||
else
|
||||
nil ->
|
||||
Logger.warning(
|
||||
Logger.error(
|
||||
"#{__MODULE__} skipped because of missing `:mrf_follow_bot, :follower_nickname` configuration, the :follower_nickname
|
||||
account does not exist, or the account is not correctly configured as a bot."
|
||||
)
|
||||
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
|
||||
_ ->
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -45,15 +45,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
|
|||
false <- User.following?(follower, user),
|
||||
false <- User.locked?(user),
|
||||
false <- (user.bio || "") |> String.downcase() |> String.contains?("nobot") do
|
||||
Logger.debug(
|
||||
"#{__MODULE__}: Follow request from #{follower.nickname} to #{user.nickname}"
|
||||
)
|
||||
|
||||
CommonAPI.follow(user, follower)
|
||||
end
|
||||
end)
|
||||
|
||||
{:ok, activity}
|
||||
{:filter, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -42,14 +42,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
|
|||
|> Map.put("cc", cc)
|
||||
|> Map.put("object", object)
|
||||
|
||||
{:ok, activity}
|
||||
{:filter, activity}
|
||||
else
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
|
|||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create", "object" => %{"tag" => tag} = object} = activity) do
|
||||
tag =
|
||||
updated_tag =
|
||||
tag
|
||||
|> prepend_author(
|
||||
object["inReplyTo"],
|
||||
|
@ -48,11 +48,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
|
|||
)
|
||||
|> Enum.uniq()
|
||||
|
||||
{:ok, put_in(activity["object"]["tag"], tag)}
|
||||
if match?(^tag, updated_tag) do
|
||||
{:pass, activity}
|
||||
else
|
||||
updated_activity = put_in(activity["object"]["tag"], updated_tag)
|
||||
{:filter, updated_activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -113,7 +113,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
|
|||
do: "<span class=\"recipients-inline\">#{added_mentions}</span>",
|
||||
else: ""
|
||||
|
||||
content =
|
||||
updated_content =
|
||||
cond do
|
||||
# For Markdown posts, insert the mentions inside the first <p> tag
|
||||
recipients_inline != "" && String.starts_with?(content, "<p>") ->
|
||||
|
@ -126,11 +126,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
|
|||
content
|
||||
end
|
||||
|
||||
{:ok, put_in(activity["object"]["content"], content)}
|
||||
if match?(^content, updated_content) do
|
||||
{:pass, activity}
|
||||
else
|
||||
updated_activity = put_in(activity["object"]["content"], updated_content)
|
||||
{:filter, updated_activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -21,7 +21,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy 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"}
|
||||
reason = "Matches with rejected keyword"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -83,23 +84,29 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
|
|||
hashtags = Object.hashtags(%Object{data: object}) ++ historical_hashtags
|
||||
|
||||
if hashtags != [] do
|
||||
with {:ok, activity} <- check_reject(activity, hashtags),
|
||||
{:ok, activity} <-
|
||||
with {:ok, processed_activity} <- check_reject(activity, hashtags),
|
||||
{:ok, processed_activity} <-
|
||||
(if type == "Create" do
|
||||
check_ftl_removal(activity, hashtags)
|
||||
check_ftl_removal(processed_activity, hashtags)
|
||||
else
|
||||
{:ok, activity}
|
||||
{:ok, processed_activity}
|
||||
end),
|
||||
{:ok, activity} <- check_sensitive(activity) do
|
||||
{:ok, activity}
|
||||
{:ok, processed_activity} <- check_sensitive(processed_activity) do
|
||||
if match?(^activity, processed_activity) do
|
||||
{:pass, processed_activity}
|
||||
else
|
||||
{:filter, processed_activity}
|
||||
end
|
||||
end
|
||||
else
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
|
|
@ -43,7 +43,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy 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}"}
|
||||
reason = "#{recipients} recipients is over the limit of #{threshold}"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -84,15 +85,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
|
||||
|
||||
with {:ok, activity} <- reject_activity(activity, reject_threshold),
|
||||
{:ok, activity} <- delist_activity(activity, delist_threshold) do
|
||||
{:ok, activity}
|
||||
else
|
||||
e -> e
|
||||
{:ok, processed_activity} <- delist_activity(activity, delist_threshold) do
|
||||
if match?(^activity, processed_activity) do
|
||||
{:pass, processed_activity}
|
||||
else
|
||||
{:filter, processed_activity}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
|
|
|
@ -31,24 +31,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
|
|||
else
|
||||
template = Pleroma.Config.get([:mrf_inline_quote, :template])
|
||||
|
||||
content =
|
||||
updated_content =
|
||||
if String.ends_with?(content, "</p>"),
|
||||
do:
|
||||
String.trim_trailing(content, "</p>") <>
|
||||
build_inline_quote(template, quote_url) <> "</p>",
|
||||
else: content <> build_inline_quote(template, quote_url)
|
||||
|
||||
Map.put(object, "content", content)
|
||||
Map.put(object, "content", updated_content)
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
|
||||
{:ok, Map.put(activity, "object", filter_object(object))}
|
||||
updated_object = filter_object(object)
|
||||
|
||||
if match?(^updated_object, object) do
|
||||
{:pass, activity}
|
||||
else
|
||||
updated_activity = Map.put(activity, "object", updated_object)
|
||||
{:filter, updated_activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
if Enum.any?(Pleroma.Config.get([:mrf_keyword, :reject]), fn pattern ->
|
||||
string_matches?(payload, pattern)
|
||||
end) do
|
||||
{:reject, "[KeywordPolicy] Matches with rejected keyword"}
|
||||
{:reject, "Matches rejected keyword"}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -112,18 +112,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
def filter(%{"type" => type, "object" => %{"content" => _content}} = activity)
|
||||
when type in ["Create", "Update"] do
|
||||
with {:ok, activity} <- check_reject(activity),
|
||||
{:ok, activity} <- check_ftl_removal(activity),
|
||||
{:ok, activity} <- check_replace(activity) do
|
||||
{:ok, activity}
|
||||
{:ok, processed_activity} <- check_ftl_removal(activity),
|
||||
{:ok, processed_activity} <- check_replace(processed_activity) do
|
||||
if match?(^activity, processed_activity) do
|
||||
{:pass, processed_activity}
|
||||
else
|
||||
{:filter, processed_activity}
|
||||
end
|
||||
else
|
||||
{:reject, nil} -> {:reject, "[KeywordPolicy] "}
|
||||
{:reject, _} = e -> e
|
||||
_e -> {:reject, "[KeywordPolicy] "}
|
||||
{:reject, reason} ->
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
|
|
@ -53,11 +53,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
|
|||
when type in ["Create", "Update"] and is_list(attachments) and length(attachments) > 0 do
|
||||
preload(activity)
|
||||
|
||||
{:ok, activity}
|
||||
{:filter, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -14,14 +14,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
|
|||
|
||||
if rejected_mention =
|
||||
Enum.find(recipients, fn recipient -> Enum.member?(reject_actors, recipient) end) do
|
||||
{:reject, "[MentionPolicy] Rejected for mention of #{rejected_mention}"}
|
||||
reason = "Rejected for mention of #{rejected_mention}"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
else
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -15,14 +15,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
|
|||
true <- note?(activity),
|
||||
false <- has_attachment?(activity),
|
||||
true <- only_mentions?(activity) do
|
||||
{:reject, "[NoEmptyPolicy]"}
|
||||
reason = "no content"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
else
|
||||
_ ->
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
defp local?(actor) do
|
||||
if actor |> String.starts_with?("#{Endpoint.url()}") do
|
||||
|
|
|
@ -8,7 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(activity) do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -17,11 +17,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
|
|||
} = activity
|
||||
)
|
||||
when type in ["Create", "Update"] and content in [".", "<p>.</p>"] do
|
||||
{:ok, put_in(activity, ["object", "content"], "")}
|
||||
{:filter, put_in(activity, ["object", "content"], "")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -16,16 +16,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
|
|||
when type in ["Create", "Update"] do
|
||||
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
|
||||
|
||||
content =
|
||||
object["content"]
|
||||
content = object["content"]
|
||||
|
||||
updated_content =
|
||||
content
|
||||
|> HTML.filter_tags(scrub_policy)
|
||||
|
||||
activity = put_in(activity, ["object", "content"], content)
|
||||
|
||||
{:ok, activity}
|
||||
if match?(^content, updated_content) do
|
||||
{:pass, activity}
|
||||
else
|
||||
updated_activity = put_in(activity, ["object", "content"], updated_content)
|
||||
{:filter, updated_activity}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -64,7 +64,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|
|||
Jason.decode(body)
|
||||
else
|
||||
error ->
|
||||
Logger.warning("""
|
||||
Logger.error("""
|
||||
[NsfwApiPolicy]: The API server failed. Skipping.
|
||||
#{inspect(error)}
|
||||
""")
|
||||
|
@ -134,17 +134,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|
|||
@impl true
|
||||
def filter(activity) do
|
||||
with {:sfw, activity} <- check_object_nsfw(activity) do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
else
|
||||
{:nsfw, _data} -> handle_nsfw(activity)
|
||||
{:nsfw, _data} ->
|
||||
handle_nsfw(activity)
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_nsfw(activity) do
|
||||
if Config.get([@policy, :reject]) do
|
||||
{:reject, activity}
|
||||
{:reject, %{activity: activity, reason: :nsfw}}
|
||||
else
|
||||
{:ok,
|
||||
{:filter,
|
||||
activity
|
||||
|> maybe_unlist()
|
||||
|> maybe_mark_sensitive()}
|
||||
|
|
|
@ -11,24 +11,17 @@ 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}} = 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, activity}
|
||||
else
|
||||
{:ttl, true} ->
|
||||
{:reject, nil}
|
||||
defp invalid_age?(%{"object" => %{"published" => published}}) do
|
||||
now = DateTime.utc_now()
|
||||
{:ok, %DateTime{} = then, _} = DateTime.from_iso8601(published)
|
||||
max_ttl = Config.get([:mrf_object_age, :threshold])
|
||||
|
||||
e ->
|
||||
{:error, e}
|
||||
end
|
||||
DateTime.diff(now, then) > max_ttl
|
||||
end
|
||||
|
||||
defp check_reject(activity, actions) do
|
||||
if :reject in actions do
|
||||
{:reject, "[ObjectAgePolicy]"}
|
||||
{:reject, %{activity: activity, reason: :object_age}}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -54,8 +47,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
|
||||
{:ok, activity}
|
||||
else
|
||||
_e ->
|
||||
{:reject, "[ObjectAgePolicy] Unhandled error"}
|
||||
e ->
|
||||
{:reject, %{activity: activity, reason: "Unhandled error", error: e}}
|
||||
end
|
||||
else
|
||||
{:ok, activity}
|
||||
|
@ -77,8 +70,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
|
||||
{:ok, activity}
|
||||
else
|
||||
_e ->
|
||||
{:reject, "[ObjectAgePolicy] Unhandled error"}
|
||||
e ->
|
||||
{:reject, %{activity: activity, reason: "Unhandled error", error: e}}
|
||||
end
|
||||
else
|
||||
{:ok, activity}
|
||||
|
@ -88,14 +81,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
@impl true
|
||||
def filter(%{"type" => "Create", "object" => %{"published" => _}} = activity) do
|
||||
with actions <- Config.get([:mrf_object_age, :actions]),
|
||||
{:reject, _} <- check_date(activity),
|
||||
true <- invalid_age?(activity),
|
||||
{:ok, activity} <- check_reject(activity, actions),
|
||||
{:ok, activity} <- check_delist(activity, actions),
|
||||
{:ok, activity} <- check_strip_followers(activity, actions) do
|
||||
{:ok, activity}
|
||||
{:filter, activity}
|
||||
else
|
||||
# check_date() is allowed to short-circuit the pipeline
|
||||
e -> e
|
||||
false ->
|
||||
{:pass, activity}
|
||||
|
||||
{:reject, _reason} = result ->
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.Policy do
|
||||
@callback filter(Pleroma.Activity.t()) :: {:ok | :reject, Pleroma.Activity.t()}
|
||||
@type legacy_return :: {:ok | :reject, map()} | {:filter, map()}
|
||||
@type return :: {:pass, map()} | {:filter, map()} | {:reject, %{activity: map(), reason: any()}}
|
||||
@callback filter(Pleroma.Activity.t()) :: legacy_return() | return()
|
||||
@callback describe() :: {:ok | :error, map()}
|
||||
@callback config_description() :: %{
|
||||
optional(:children) => [map()],
|
||||
|
|
|
@ -46,14 +46,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuietReply do
|
|||
|> put_in(["object", "to"], updated_to)
|
||||
|> put_in(["object", "cc"], updated_cc)
|
||||
|
||||
{:ok, updated_activity}
|
||||
{:filter, updated_activity}
|
||||
else
|
||||
_ -> {:ok, activity}
|
||||
_ ->
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -12,11 +12,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
|
||||
{:ok, Map.put(activity, "object", filter_object(object))}
|
||||
updated_object = filter_object(object)
|
||||
|
||||
if match?(^object, updated_object) do
|
||||
{:pass, activity}
|
||||
else
|
||||
updated_activity = Map.put(activity, "object", updated_object)
|
||||
{:filter, updated_activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -13,15 +13,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
|
|||
require Pleroma.Constants
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create"} = object) do
|
||||
user = User.get_cached_by_ap_id(object["actor"])
|
||||
def filter(%{"type" => "Create"} = activity) do
|
||||
user = User.get_cached_by_ap_id(activity["actor"])
|
||||
|
||||
# Determine visibility
|
||||
visibility =
|
||||
cond do
|
||||
Pleroma.Constants.as_public() in object["to"] -> "public"
|
||||
Pleroma.Constants.as_public() in object["cc"] -> "unlisted"
|
||||
user.follower_address in object["to"] -> "followers"
|
||||
Pleroma.Constants.as_public() in activity["to"] -> "public"
|
||||
Pleroma.Constants.as_public() in activity["cc"] -> "unlisted"
|
||||
user.follower_address in activity["to"] -> "followers"
|
||||
true -> "direct"
|
||||
end
|
||||
|
||||
|
@ -29,21 +29,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
|
|||
|
||||
cond do
|
||||
visibility in ["public", "unlisted"] ->
|
||||
{:ok, object}
|
||||
{:pass, activity}
|
||||
|
||||
visibility == "followers" and Keyword.get(policy, :allow_followersonly) ->
|
||||
{:ok, object}
|
||||
{:pass, activity}
|
||||
|
||||
visibility == "direct" and Keyword.get(policy, :allow_direct) ->
|
||||
{:ok, object}
|
||||
{:pass, activity}
|
||||
|
||||
true ->
|
||||
{:reject, "[RejectNonPublic] visibility: #{visibility}"}
|
||||
reason = "visibility: #{visibility}"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
|
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
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"}
|
||||
true -> {:reject, %{activity: activity, reason: "host not in accept list"}}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
|> MRF.subdomains_regex()
|
||||
|
||||
if MRF.subdomain_match?(rejects, actor_host) do
|
||||
{:reject, "[SimplePolicy] host in reject list"}
|
||||
{:reject, %{activity: activity, reason: "host in reject list"}}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -142,7 +142,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
|> MRF.subdomains_regex()
|
||||
|
||||
if MRF.subdomain_match?(report_removal, actor_host) do
|
||||
{:reject, "[SimplePolicy] host in report_removal list"}
|
||||
{:reject, %{activity: activity, reason: "host in report_removal list"}}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -200,7 +200,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
|> MRF.subdomains_regex()
|
||||
|
||||
if MRF.subdomain_match?(reject_deletes, actor_host) do
|
||||
{:reject, "[SimplePolicy] host in reject_deletes list"}
|
||||
{:reject, %{activity: activity, reason: "host in reject_deletes list"}}
|
||||
else
|
||||
{:ok, activity}
|
||||
end
|
||||
|
@ -218,9 +218,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
{:ok, activity} <- check_followers_only(actor_info, activity),
|
||||
{:ok, activity} <- check_report_removal(actor_info, activity),
|
||||
{:ok, activity} <- check_object(activity) do
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
{:reject, _} = result ->
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -232,24 +233,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
{: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}
|
||||
{:pass, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
{:reject, _} = result ->
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity) when is_binary(activity) do
|
||||
uri = URI.parse(activity)
|
||||
def filter(ap_id) when is_binary(ap_id) do
|
||||
uri = URI.parse(ap_id)
|
||||
|
||||
with {:ok, activity} <- check_accept(uri, activity),
|
||||
{:ok, activity} <- check_reject(uri, activity) do
|
||||
{:ok, activity}
|
||||
with {_, {:ok, ap_id}} <- {:check_accept, check_accept(uri, ap_id)},
|
||||
{_, {:ok, ap_id}} <- {:check_reject, check_reject(uri, ap_id)} do
|
||||
{:pass, ap_id}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
{:check_accept, {:reject, _}} ->
|
||||
fake_activity = %{data: %{id: ap_id}}
|
||||
{:reject, %{activity: fake_activity, reason: "Host not in accept list"}}
|
||||
|
||||
{:check_reject, {:reject, _}} ->
|
||||
fake_activity = %{data: %{id: ap_id}}
|
||||
{:reject, %{activity: fake_activity, reason: "Host in reject list"}}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
|
|
@ -97,10 +97,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
{:ok, activity}
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec config_description :: %{
|
||||
|
|
|
@ -6,8 +6,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
require Logger
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
defp lookup_subchain(actor) do
|
||||
|
@ -21,19 +19,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
|||
|
||||
@impl true
|
||||
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)}"
|
||||
)
|
||||
|
||||
with {:ok, _match, subchain} <- lookup_subchain(actor) do
|
||||
MRF.filter(subchain, activity)
|
||||
else
|
||||
_e -> {:ok, activity}
|
||||
_e ->
|
||||
{:pass, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -125,26 +125,40 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
if user.local == true do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject,
|
||||
"[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-remote-subscription"}
|
||||
reason = "Follow from #{actor} tagged with mrf_tag:disable-remote-subscription"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
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(
|
||||
"mrf_tag:disable-any-subscription",
|
||||
%{"type" => "Follow", "actor" => actor} = activity
|
||||
) do
|
||||
reason = "Follow from #{actor} tagged with mrf_tag:disable-any-subscription"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
|
||||
defp process_tag(_, activity), do: {:ok, activity}
|
||||
|
||||
def filter_activity(actor, activity) do
|
||||
User.get_cached_by_ap_id(actor)
|
||||
|> get_tags()
|
||||
|> Enum.reduce({:ok, activity}, fn
|
||||
tag, {:ok, activity} ->
|
||||
process_tag(tag, activity)
|
||||
result =
|
||||
User.get_cached_by_ap_id(actor)
|
||||
|> get_tags()
|
||||
|> Enum.reduce({:ok, activity}, fn
|
||||
tag, {:ok, activity} ->
|
||||
process_tag(tag, activity)
|
||||
|
||||
_, error ->
|
||||
error
|
||||
end)
|
||||
_, error ->
|
||||
error
|
||||
end)
|
||||
|
||||
case result do
|
||||
{:ok, activity} ->
|
||||
{:pass, activity}
|
||||
|
||||
{:reject, _} = reject ->
|
||||
reject
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
@ -156,7 +170,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
do: filter_activity(actor, activity)
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -14,7 +14,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
|
|||
if actor in allow_list do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, "[UserAllowListPolicy] #{actor} not in the list"}
|
||||
reason = "#{actor} not in the list"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -28,10 +29,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
|
|||
[]
|
||||
)
|
||||
|
||||
filter_by_list(activity, allow_list)
|
||||
case filter_by_list(activity, allow_list) do
|
||||
{:ok, activity} ->
|
||||
{:pass, activity}
|
||||
|
||||
{:reject, _} = reject ->
|
||||
reject
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
|
|
@ -8,33 +8,36 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
|
|||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Undo", "object" => object} = activity) do
|
||||
with {:ok, _} <- filter(object) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
end
|
||||
end
|
||||
def filter(%{"type" => "Undo", "object" => object} = _activity), do: filter(object)
|
||||
|
||||
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,
|
||||
{:accepted_vocab,
|
||||
Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, activity_type)},
|
||||
{_, false} <-
|
||||
{:rejected,
|
||||
{:rejected_vocab,
|
||||
length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, activity_type)},
|
||||
{:ok, _} <- filter(activity["object"]) do
|
||||
{:ok, activity}
|
||||
{:pass, _} <- filter(activity["object"]) do
|
||||
{:pass, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
{:accepted, _} -> {:reject, "[VocabularyPolicy] #{activity_type} not in accept list"}
|
||||
{:rejected, _} -> {:reject, "[VocabularyPolicy] #{activity_type} in reject list"}
|
||||
{:reject, reason} ->
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
|
||||
{:accepted_vocab, _} ->
|
||||
reason = "#{activity_type} not in accept list"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
|
||||
{:rejected_vocab, _} ->
|
||||
reason = "#{activity_type} in reject list"
|
||||
{:reject, %{activity: activity, reason: reason}}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(activity), do: {:ok, activity}
|
||||
def filter(activity) do
|
||||
{:pass, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
|
|
|
@ -10,7 +10,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
@local_actor Pleroma.Web.Endpoint.url() <> "/users/cofe"
|
||||
|
||||
test "adds `expires_at` property" do
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
assert {:filter, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => @id,
|
||||
"actor" => @local_actor,
|
||||
|
@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
test "keeps existing `expires_at` if it less than the config setting" do
|
||||
expires_at = DateTime.utc_now() |> Timex.shift(days: 1)
|
||||
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =
|
||||
assert {:pass, %{"type" => "Create", "expires_at" => ^expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => @id,
|
||||
"actor" => @local_actor,
|
||||
|
@ -37,7 +37,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
test "overwrites existing `expires_at` if it greater than the config setting" do
|
||||
too_distant_future = DateTime.utc_now() |> Timex.shift(years: 2)
|
||||
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
assert {:filter, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => @id,
|
||||
"actor" => @local_actor,
|
||||
|
@ -50,7 +50,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
end
|
||||
|
||||
test "ignores remote activities" do
|
||||
assert {:ok, activity} =
|
||||
assert {:pass, activity} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => "https://example.com/123",
|
||||
"actor" => "https://example.com/users/cofe",
|
||||
|
@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
end
|
||||
|
||||
test "ignores non-Create/Note activities" do
|
||||
assert {:ok, activity} =
|
||||
assert {:pass, activity} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => "https://example.com/123",
|
||||
"actor" => "https://example.com/users/cofe",
|
||||
|
@ -71,7 +71,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
|
||||
refute Map.has_key?(activity, "expires_at")
|
||||
|
||||
assert {:ok, activity} =
|
||||
assert {:pass, activity} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => "https://example.com/123",
|
||||
"actor" => "https://example.com/users/cofe",
|
||||
|
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
|||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||
assert {:reject, %{reason: "Scored" <> _}} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "matches followbots by display name" do
|
||||
|
@ -37,7 +37,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
|||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||
assert {:reject, %{reason: "Scored" <> _}} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "matches followbots by actor_type" do
|
||||
|
@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
|||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||
assert {:reject, %{reason: "Scored" <> _}} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -69,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
|||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||
{:pass, _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "bots if the target follows the bots" do
|
||||
|
@ -86,7 +86,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
|||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||
{:pass, _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -102,6 +102,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
|
|||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||
{:pass, _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue