From 50f7b6367ffd889eb051f26e6f50eaab5229754e Mon Sep 17 00:00:00 2001 From: Norm Date: Fri, 25 Oct 2024 15:55:17 -0400 Subject: [PATCH] MRF.ObjectAgePolicy: Check objects alongside Create activities ObjectAgePolicy only checked Create activites, which still resulted in some old posts making it to user timelines, even when it was enabled. This fixes that issue by also checking objects of an updatable type as defined in `Pleroma.Constants.updatable_object_types`. --- lib/pleroma/constants.ex | 24 +++---- .../web/activity_pub/mrf/object_age_policy.ex | 62 +++++++++++++++---- .../mrf/object_age_policy_test.exs | 9 +++ 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index 2681d7671..0f4be3b78 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -43,17 +43,19 @@ defmodule Pleroma.Constants do ] ) - const(updatable_object_types, - do: [ - "Note", - "Question", - "Audio", - "Video", - "Event", - "Article", - "Page" - ] - ) + @updatable_object_types [ + "Note", + "Question", + "Audio", + "Video", + "Event", + "Article", + "Page" + ] + + const(updatable_object_types, do: @updatable_object_types) + + const(object_types, do: @updatable_object_types ++ ["Answer"]) const(actor_types, do: [ 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 02c9b18ed..1cdb507f0 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,36 @@ 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 update_to_cc(message, to, cc) do + message = + message + |> Map.put("to", to) + |> Map.put("cc", cc) + + if Map.has_key?(message, "object") do + message + |> Kernel.put_in(["object", "to"], to) + |> Kernel.put_in(["object", "cc"], cc) + else + message + end + end + + defp check_date(%{"object" => %{"published" => _} = object} = activity) do + with {:ok, object} <- check_date(object) do + activity = activity |> Map.put("object", object) + {:ok, activity} + else + e -> e + end + end + + defp check_date(%{"published" => published} = object) 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, object} else {:ttl, true} -> {:reject, nil} @@ -47,10 +71,7 @@ defp check_delist(message, actions) do message = message - |> Map.put("to", to) - |> Map.put("cc", cc) - |> Kernel.put_in(["object", "to"], to) - |> Kernel.put_in(["object", "cc"], cc) + |> update_to_cc(to, cc) {:ok, message} else @@ -70,10 +91,7 @@ defp check_strip_followers(message, actions) do message = message - |> Map.put("to", to) - |> Map.put("cc", cc) - |> Kernel.put_in(["object", "to"], to) - |> Kernel.put_in(["object", "cc"], cc) + |> update_to_cc(to, cc) {:ok, message} else @@ -85,11 +103,18 @@ defp check_strip_followers(message, actions) do end end - @impl true - def filter(%{"type" => "Create", "object" => %{"published" => _}} = message) do + defp maybe_check_reject(message, _actions, false) do + {:ok, message} + end + + defp maybe_check_reject(message, actions, true) do + check_reject(message, actions) + end + + defp check(message, allow_reject) do with actions <- Config.get([:mrf_object_age, :actions]), {:reject, _} <- check_date(message), - {:ok, message} <- check_reject(message, actions), + {:ok, message} <- maybe_check_reject(message, actions, allow_reject), {:ok, message} <- check_delist(message, actions), {:ok, message} <- check_strip_followers(message, actions) do {:ok, message} @@ -99,6 +124,17 @@ def filter(%{"type" => "Create", "object" => %{"published" => _}} = message) do end end + @impl true + def filter(%{"type" => "Create", "object" => %{"published" => _}} = message) do + check(message, true) + end + + @impl true + def filter(%{"type" => type, "published" => _} = message) + when type in Pleroma.Constants.object_types() do + check(message, false) + end + @impl true def filter(message), do: {:ok, message} diff --git a/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs b/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs index 2f649a0a4..1d571bb46 100644 --- a/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs +++ b/test/pleroma/web/activity_pub/mrf/object_age_policy_test.exs @@ -57,6 +57,15 @@ test "it rejects an old post" do assert match?({:reject, _}, ObjectAgePolicy.filter(data)) end + test "it doesn't reject a fetched post" do + clear_config([:mrf_object_age, :actions], [:reject]) + + data = get_old_message() + object = data["object"] + + assert match?({:ok, _}, ObjectAgePolicy.filter(object)) + end + test "it allows a new post" do clear_config([:mrf_object_age, :actions], [:reject])