Make EnsureRePrepended history-aware

This commit is contained in:
Tusooa Zhu 2022-07-23 17:48:39 -04:00
parent eba9b0760f
commit cd19537f39
No known key found for this signature in database
GPG Key ID: 7B467EDE43A08224
5 changed files with 102 additions and 7 deletions

View File

@ -198,7 +198,7 @@ defmodule Pleroma.Object.Updater do
} }
end end
defp for_each_history_item(%{"orderedItems" => items} = history, _object, fun) do def for_each_history_item(%{"orderedItems" => items} = history, _object, fun) do
new_items = new_items =
Enum.map(items, fun) Enum.map(items, fun)
|> Enum.reduce_while( |> Enum.reduce_while(
@ -215,7 +215,7 @@ defmodule Pleroma.Object.Updater do
end end
end end
defp for_each_history_item(history, _, _) do def for_each_history_item(history, _, _) do
{:ok, history} {:ok, history}
end end

View File

@ -53,10 +53,53 @@ defmodule Pleroma.Web.ActivityPub.MRF do
@required_description_keys [:key, :related_policy] @required_description_keys [:key, :related_policy]
def filter_one(policy, message) do
should_plug_history? =
if function_exported?(policy, :history_awareness, 0) do
policy.history_awareness()
else
:manual
end
|> Kernel.==(:auto)
if not should_plug_history? do
policy.filter(message)
else
main_result = policy.filter(message)
with {_, {:ok, main_message}} <- {:main, main_result},
{_,
%{
"formerRepresentations" => %{
"orderedItems" => [_ | _]
}
}} = {_, object} <- {:object, message["object"]},
{_, {:ok, new_history}} <-
{:history,
Pleroma.Object.Updater.for_each_history_item(
object["formerRepresentations"],
object,
fn item ->
with {:ok, filtered} <- policy.filter(Map.put(message, "object", item)) do
{:ok, filtered["object"]}
else
e -> e
end
end
)} do
{:ok, put_in(main_message, ["object", "formerRepresentations"], new_history)}
else
{:main, _} -> main_result
{:object, _} -> main_result
{:history, e} -> e
end
end
end
def filter(policies, %{} = message) do def filter(policies, %{} = message) do
policies policies
|> Enum.reduce({:ok, message}, fn |> Enum.reduce({:ok, message}, fn
policy, {:ok, message} -> policy.filter(message) policy, {:ok, message} -> filter_one(policy, message)
_, error -> error _, error -> error
end) end)
end end

View File

@ -10,6 +10,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
@reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless]) @reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless])
def history_awareness, do: :auto
def filter_by_summary( def filter_by_summary(
%{data: %{"summary" => parent_summary}} = _in_reply_to, %{data: %{"summary" => parent_summary}} = _in_reply_to,
%{"summary" => child_summary} = child %{"summary" => child_summary} = child
@ -27,8 +29,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
def filter_by_summary(_in_reply_to, child), do: child def filter_by_summary(_in_reply_to, child), do: child
def filter(%{"type" => "Create", "object" => child_object} = object) def filter(%{"type" => type, "object" => child_object} = object)
when is_map(child_object) do when type in ["Create", "Update"] and is_map(child_object) do
child = child =
child_object["inReplyTo"] child_object["inReplyTo"]
|> Object.normalize(fetch: false) |> Object.normalize(fetch: false)

View File

@ -12,5 +12,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.Policy do
label: String.t(), label: String.t(),
description: String.t() description: String.t()
} }
@optional_callbacks config_description: 0 @callback history_awareness() :: :auto | :manual
@optional_callbacks config_description: 0, history_awareness: 0
end end

View File

@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
describe "rewrites summary" do describe "rewrites summary" do
@ -35,10 +36,58 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
assert {:ok, res} = EnsureRePrepended.filter(message) assert {:ok, res} = EnsureRePrepended.filter(message)
assert res["object"]["summary"] == "re: object-summary" assert res["object"]["summary"] == "re: object-summary"
end end
test "it adds `re:` to history" do
message = %{
"type" => "Create",
"object" => %{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}},
"formerRepresentations" => %{
"orderedItems" => [
%{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
}
]
}
}
}
assert {:ok, res} = MRF.filter_one(EnsureRePrepended, message)
assert res["object"]["summary"] == "re: object-summary"
assert Enum.at(res["object"]["formerRepresentations"]["orderedItems"], 0)["summary"] ==
"re: object-summary"
end
test "it accepts Updates" do
message = %{
"type" => "Update",
"object" => %{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}},
"formerRepresentations" => %{
"orderedItems" => [
%{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
}
]
}
}
}
assert {:ok, res} = MRF.filter_one(EnsureRePrepended, message)
assert res["object"]["summary"] == "re: object-summary"
assert Enum.at(res["object"]["formerRepresentations"]["orderedItems"], 0)["summary"] ==
"re: object-summary"
end
end end
describe "skip filter" do describe "skip filter" do
test "it skip if type isn't 'Create'" do test "it skip if type isn't 'Create' or 'Update'" do
message = %{ message = %{
"type" => "Annotation", "type" => "Annotation",
"object" => %{"summary" => "object-summary"} "object" => %{"summary" => "object-summary"}