logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/
commit: bc1b4f0be7c53f1d6b6b01d0964f09d792b1a192
parent 196f1088232c1b1d725762f0c6379992fd510fd2
Author: Haelwenn <contact+git.pleroma.social@hacktivis.me>
Date:   Sat, 21 Sep 2024 12:27:35 +0000

Merge branch 'features/mrf-id_filter' into 'develop'

Add id_filter to MRFs

See merge request pleroma/pleroma!3858

Diffstat:

Achangelog.d/mrf-id_filter.add2++
Mlib/pleroma/object/fetcher.ex4++++
Mlib/pleroma/web/activity_pub/mrf.ex8++++++++
Mlib/pleroma/web/activity_pub/mrf/drop_policy.ex6++++++
Mlib/pleroma/web/activity_pub/mrf/policy.ex3++-
Mlib/pleroma/web/activity_pub/mrf/simple_policy.ex12++++++++++++
Mtest/pleroma/web/activity_pub/mrf/simple_policy_test.exs15+++++++++++++++
7 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/changelog.d/mrf-id_filter.add b/changelog.d/mrf-id_filter.add @@ -0,0 +1 @@ +Add `id_filter` to MRF to filter URLs and their domain prior to fetching +\ No newline at end of file diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex @@ -145,6 +145,7 @@ defmodule Pleroma.Object.Fetcher do Logger.debug("Fetching object #{id} via AP") with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")}, + {_, true} <- {:mrf, MRF.id_filter(id)}, {:ok, body} <- get_object(id), {:ok, data} <- safe_json_decode(body), :ok <- Containment.contain_origin_from_id(id, data) do @@ -160,6 +161,9 @@ defmodule Pleroma.Object.Fetcher do {:error, e} -> {:error, e} + {:mrf, false} -> + {:error, {:reject, "Filtered by id"}} + e -> {:error, e} end diff --git 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/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex @@ -14,5 +14,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do end @impl true + def id_filter(id) do + Logger.debug("REJECTING #{id}") + false + end + + @impl true def describe, do: {:ok, %{}} end diff --git a/lib/pleroma/web/activity_pub/mrf/policy.ex b/lib/pleroma/web/activity_pub/mrf/policy.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.Policy do @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/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex @@ -192,6 +192,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do end @impl true + 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) diff --git a/test/pleroma/web/activity_pub/mrf/simple_policy_test.exs b/test/pleroma/web/activity_pub/mrf/simple_policy_test.exs @@ -252,6 +252,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do remote_message = build_remote_message() assert SimplePolicy.filter(remote_message) == {:ok, remote_message} + assert SimplePolicy.id_filter(remote_message["actor"]) end test "activity has a matching host" do @@ -260,6 +261,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do remote_message = build_remote_message() assert {:reject, _} = SimplePolicy.filter(remote_message) + refute SimplePolicy.id_filter(remote_message["actor"]) end test "activity matches with wildcard domain" do @@ -268,6 +270,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do remote_message = build_remote_message() assert {:reject, _} = SimplePolicy.filter(remote_message) + refute SimplePolicy.id_filter(remote_message["actor"]) end test "actor has a matching host" do @@ -276,6 +279,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do remote_user = build_remote_user() assert {:reject, _} = SimplePolicy.filter(remote_user) + refute SimplePolicy.id_filter(remote_user["id"]) end test "reject Announce when object would be rejected" do @@ -288,6 +292,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do } assert {:reject, _} = SimplePolicy.filter(announce) + # Note: Non-Applicable for id_filter/1 end test "reject by URI object" do @@ -300,6 +305,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do } assert {:reject, _} = SimplePolicy.filter(announce) + # Note: Non-Applicable for id_filter/1 end end @@ -370,6 +376,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do assert SimplePolicy.filter(local_message) == {:ok, local_message} assert SimplePolicy.filter(remote_message) == {:ok, remote_message} + assert SimplePolicy.id_filter(local_message["actor"]) + assert SimplePolicy.id_filter(remote_message["actor"]) end test "is not empty but activity doesn't have a matching host" do @@ -380,6 +388,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do assert SimplePolicy.filter(local_message) == {:ok, local_message} assert {:reject, _} = SimplePolicy.filter(remote_message) + assert SimplePolicy.id_filter(local_message["actor"]) + refute SimplePolicy.id_filter(remote_message["actor"]) end test "activity has a matching host" do @@ -390,6 +400,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do assert SimplePolicy.filter(local_message) == {:ok, local_message} assert SimplePolicy.filter(remote_message) == {:ok, remote_message} + assert SimplePolicy.id_filter(local_message["actor"]) + assert SimplePolicy.id_filter(remote_message["actor"]) end test "activity matches with wildcard domain" do @@ -400,6 +412,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do assert SimplePolicy.filter(local_message) == {:ok, local_message} assert SimplePolicy.filter(remote_message) == {:ok, remote_message} + assert SimplePolicy.id_filter(local_message["actor"]) + assert SimplePolicy.id_filter(remote_message["actor"]) end test "actor has a matching host" do @@ -408,6 +422,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do remote_user = build_remote_user() assert SimplePolicy.filter(remote_user) == {:ok, remote_user} + assert SimplePolicy.id_filter(remote_user["id"]) end end