Objects who got updated would just pass through several of the MRF policies, undoing moderation in some situations.
In the relevant cases we now check not only for Create activities, but also Update activities.
I checked which ones checked explicitly on type Create using `grep '"type" => "Create"' lib/pleroma/web/activity_pub/mrf/*`.
The following from that list have not been changed:
* lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
* Not relevant for moderation
* lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
* Already had a test for Update
* lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
* In practice only relevant when fetching old objects (e.g. through Like or Announce). These are always wrapped in a Create.
* lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
* We don't allow changing scope with Update, so not relevant here
13 files changed:
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do
- @moduledoc "Adds expiration to all local Create activities"
+ @moduledoc "Adds expiration to all local Create/Update activities"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
String.starts_with?(actor, Pleroma.Web.Endpoint.url())
end
String.starts_with?(actor, Pleroma.Web.Endpoint.url())
end
- defp note?(activity) do
- match?(%{"type" => "Create", "object" => %{"type" => "Note"}}, activity)
+ defp note?(%{"type" => type, "object" => %{"type" => "Note"}})
+ when type in ["Create", "Update"] do
+ true
+ end
+
+ defp note?(_) do
+ false
end
defp maybe_add_expiration(activity) do
end
defp maybe_add_expiration(activity) do
defp contains_links?(_), do: false
@impl true
defp contains_links?(_), do: false
@impl true
- def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
+ def filter(%{"type" => type, "actor" => actor, "object" => object} = message)
+ when type in ["Create", "Update"] 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
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
@impl true
def filter(
%{
@impl true
def filter(
%{
"to" => to,
"cc" => cc,
"actor" => actor,
"object" => object
} = message
"to" => to,
"cc" => cc,
"actor" => actor,
"object" => object
} = message
+ )
+ when type in ["Create", "Update"] do
user = User.get_cached_by_ap_id(actor)
isbot = check_if_bot(user)
user = User.get_cached_by_ap_id(actor)
isbot = check_if_bot(user)
- def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = message)
- when object_type in ~w{Note Article} do
+ def filter(%{"type" => type, "object" => %{"type" => object_type}} = message)
+ when type in ~w{Create Update} and object_type in ~w{Note Article} do
reject_threshold =
Pleroma.Config.get(
[:mrf_hellthread, :reject_threshold],
reject_threshold =
Pleroma.Config.get(
[:mrf_hellthread, :reject_threshold],
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@impl true
- def filter(%{"type" => "Create"} = message) do
+ def filter(%{"type" => type} = message) when type in ["Create", "Update"] do
reject_actors = Pleroma.Config.get([:mrf_mention, :actors], [])
recipients = (message["to"] || []) ++ (message["cc"] || [])
reject_actors = Pleroma.Config.get([:mrf_mention, :actors], [])
recipients = (message["to"] || []) ++ (message["cc"] || [])
defp check_media_removal(
%{host: actor_host} = _actor_info,
defp check_media_removal(
%{host: actor_host} = _actor_info,
- %{"type" => "Create", "object" => %{"attachment" => child_attachment}} = object
+ %{"type" => type, "object" => %{"attachment" => child_attachment}} = object
- when length(child_attachment) > 0 do
+ when type in ["Create", "Update"] and length(child_attachment) > 0 do
media_removal =
instance_list(:media_removal)
|> MRF.subdomains_regex()
media_removal =
instance_list(:media_removal)
|> MRF.subdomains_regex()
defp check_media_nsfw(
%{host: actor_host} = _actor_info,
%{
defp check_media_nsfw(
%{host: actor_host} = _actor_info,
%{
"object" => %{} = _child_object
} = object
"object" => %{} = _child_object
} = object
+ )
+ when type in ["Create", "Update"] do
media_nsfw =
instance_list(:media_nsfw)
|> MRF.subdomains_regex()
media_nsfw =
instance_list(:media_nsfw)
|> MRF.subdomains_regex()
"actor" => actor,
"object" => object
} = message
"actor" => actor,
"object" => object
} = message
- ) when type in ["Create", "Update"] do
+ )
+ when type in ["Create", "Update"] do
user = User.get_cached_by_ap_id(actor)
if Enum.member?(to, Pleroma.Constants.as_public()) do
user = User.get_cached_by_ap_id(actor)
if Enum.member?(to, Pleroma.Constants.as_public()) do
"actor" => actor,
"object" => object
} = message
"actor" => actor,
"object" => object
} = message
- ) when type in ["Create", "Update"] do
+ )
+ when type in ["Create", "Update"] do
user = User.get_cached_by_ap_id(actor)
if Enum.member?(to, Pleroma.Constants.as_public()) or
user = User.get_cached_by_ap_id(actor)
if Enum.member?(to, Pleroma.Constants.as_public()) or
})
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
})
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
+
+ assert {:ok, %{"type" => "Update", "expires_at" => expires_at}} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => @id,
+ "actor" => @local_actor,
+ "type" => "Update",
+ "object" => %{"type" => "Note"}
+ })
+
+ assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
end
test "keeps existing `expires_at` if it less than the config setting" do
end
test "keeps existing `expires_at` if it less than the config setting" do
"expires_at" => expires_at,
"object" => %{"type" => "Note"}
})
"expires_at" => expires_at,
"object" => %{"type" => "Note"}
})
+
+ assert {:ok, %{"type" => "Update", "expires_at" => ^expires_at}} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => @id,
+ "actor" => @local_actor,
+ "type" => "Update",
+ "expires_at" => expires_at,
+ "object" => %{"type" => "Note"}
+ })
end
test "overwrites existing `expires_at` if it greater than the config setting" do
end
test "overwrites existing `expires_at` if it greater than the config setting" do
})
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
})
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
+
+ assert {:ok, %{"type" => "Update", "expires_at" => expires_at}} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => @id,
+ "actor" => @local_actor,
+ "type" => "Update",
+ "expires_at" => too_distant_future,
+ "object" => %{"type" => "Note"}
+ })
+
+ assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
end
test "ignores remote activities" do
end
test "ignores remote activities" do
})
refute Map.has_key?(activity, "expires_at")
})
refute Map.has_key?(activity, "expires_at")
+
+ assert {:ok, activity} =
+ ActivityExpirationPolicy.filter(%{
+ "id" => "https://example.com/123",
+ "actor" => "https://example.com/users/cofe",
+ "type" => "Update",
+ "object" => %{"type" => "Note"}
+ })
+
+ refute Map.has_key?(activity, "expires_at")
- test "ignores non-Create/Note activities" do
+ test "ignores non-Create/Update/Note activities" do
assert {:ok, activity} =
ActivityExpirationPolicy.filter(%{
"id" => "https://example.com/123",
assert {:ok, activity} =
ActivityExpirationPolicy.filter(%{
"id" => "https://example.com/123",
+ @linkless_update_message %{
+ "type" => "Update",
+ "object" => %{
+ "content" => "hi world!"
+ }
+ }
+
+ @linkful_update_message %{
+ "type" => "Update",
+ "object" => %{
+ "content" => "<a href='https://example.com'>hi world!</a>"
+ }
+ }
+
+ @response_update_message %{
+ "type" => "Update",
+ "object" => %{
+ "name" => "yes",
+ "type" => "Answer"
+ }
+ }
+
describe "with new user" do
test "it allows posts without links" do
user = insert(:user, local: false)
describe "with new user" do
test "it allows posts without links" do
user = insert(:user, local: false)
@linkless_message
|> Map.put("actor", user.ap_id)
@linkless_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkless_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
end
test "it disallows posts with links" do
end
test "it disallows posts with links" do
+ update_message = %{
+ "type" => "Update",
+ "actor" => user.ap_id,
+ "object" => %{
+ "formerRepresentations" => %{
+ "type" => "OrderedCollection",
+ "orderedItems" => [
+ %{
+ "content" => "<a href='https://example.com'>hi world!</a>"
+ }
+ ]
+ },
+ "content" => "mew"
+ }
+ }
+
{:reject, _} = MRF.filter_one(AntiLinkSpamPolicy, message)
{:reject, _} = MRF.filter_one(AntiLinkSpamPolicy, message)
+ {:reject, _} = MRF.filter_one(AntiLinkSpamPolicy, update_message)
end
test "it allows posts with links for local users" do
end
test "it allows posts with links for local users" do
@linkful_message
|> Map.put("actor", user.ap_id)
@linkful_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkful_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
end
test "it disallows posts with links in history" do
end
test "it disallows posts with links in history" do
@linkful_message
|> Map.put("actor", user.ap_id)
@linkful_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkful_update_message
+ |> Map.put("actor", user.ap_id)
+
{:reject, _} = AntiLinkSpamPolicy.filter(message)
{:reject, _} = AntiLinkSpamPolicy.filter(message)
+ {:reject, _} = AntiLinkSpamPolicy.filter(update_message)
@linkless_message
|> Map.put("actor", user.ap_id)
@linkless_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkless_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
end
test "it allows posts with links" do
end
test "it allows posts with links" do
@linkful_message
|> Map.put("actor", user.ap_id)
@linkful_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkful_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
@linkless_message
|> Map.put("actor", user.ap_id)
@linkless_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkless_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
end
test "it allows posts with links" do
end
test "it allows posts with links" do
@linkful_message
|> Map.put("actor", user.ap_id)
@linkful_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @linkful_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
@linkless_message
|> Map.put("actor", "http://invalid.actor")
@linkless_message
|> Map.put("actor", "http://invalid.actor")
+ update_message =
+ @linkless_update_message
+ |> Map.put("actor", "http://invalid.actor")
+
assert capture_log(fn ->
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
assert capture_log(fn ->
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
+
+ assert capture_log(fn ->
+ {:reject, _} = AntiLinkSpamPolicy.filter(update_message)
+ end) =~ "[error] Could not decode user at fetch http://invalid.actor"
end
test "it rejects posts with links" do
end
test "it rejects posts with links" do
@linkful_message
|> Map.put("actor", "http://invalid.actor")
@linkful_message
|> Map.put("actor", "http://invalid.actor")
+ update_message =
+ @linkful_update_message
+ |> Map.put("actor", "http://invalid.actor")
+
assert capture_log(fn ->
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
assert capture_log(fn ->
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
+
+ assert capture_log(fn ->
+ {:reject, _} = AntiLinkSpamPolicy.filter(update_message)
+ end) =~ "[error] Could not decode user at fetch http://invalid.actor"
@response_message
|> Map.put("actor", user.ap_id)
@response_message
|> Map.put("actor", user.ap_id)
+ update_message =
+ @response_update_message
+ |> Map.put("actor", user.ap_id)
+
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
+ {:ok, _update_message} = AntiLinkSpamPolicy.filter(update_message)
+ defp generate_update_messages(actor) do
+ {%{
+ "actor" => actor.ap_id,
+ "type" => "Update",
+ "object" => %{},
+ "to" => [@public, "f"],
+ "cc" => [actor.follower_address, "d"]
+ },
+ %{
+ "actor" => actor.ap_id,
+ "type" => "Update",
+ "object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
+ "to" => ["f", actor.follower_address],
+ "cc" => ["d", @public]
+ }}
+ end
+
test "removes from the federated timeline by nickname heuristics 1" do
actor = insert(:user, %{nickname: "annoying_ebooks@example.com"})
{message, except_message} = generate_messages(actor)
test "removes from the federated timeline by nickname heuristics 1" do
actor = insert(:user, %{nickname: "annoying_ebooks@example.com"})
{message, except_message} = generate_messages(actor)
+ {update_message, except_update_message} = generate_update_messages(actor)
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ assert ForceBotUnlistedPolicy.filter(update_message) == {:ok, except_update_message}
end
test "removes from the federated timeline by nickname heuristics 2" do
actor = insert(:user, %{nickname: "cirnonewsnetworkbot@meow.cat"})
{message, except_message} = generate_messages(actor)
end
test "removes from the federated timeline by nickname heuristics 2" do
actor = insert(:user, %{nickname: "cirnonewsnetworkbot@meow.cat"})
{message, except_message} = generate_messages(actor)
+ {update_message, except_update_message} = generate_update_messages(actor)
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ assert ForceBotUnlistedPolicy.filter(update_message) == {:ok, except_update_message}
end
test "removes from the federated timeline by actor type Application" do
actor = insert(:user, %{actor_type: "Application"})
{message, except_message} = generate_messages(actor)
end
test "removes from the federated timeline by actor type Application" do
actor = insert(:user, %{actor_type: "Application"})
{message, except_message} = generate_messages(actor)
+ {update_message, except_update_message} = generate_update_messages(actor)
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ assert ForceBotUnlistedPolicy.filter(update_message) == {:ok, except_update_message}
end
test "removes from the federated timeline by actor type Service" do
actor = insert(:user, %{actor_type: "Service"})
{message, except_message} = generate_messages(actor)
end
test "removes from the federated timeline by actor type Service" do
actor = insert(:user, %{actor_type: "Service"})
{message, except_message} = generate_messages(actor)
+ {update_message, except_update_message} = generate_update_messages(actor)
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
+ assert ForceBotUnlistedPolicy.filter(update_message) == {:ok, except_update_message}
- [user: user, message: message]
+ update_message = %{
+ "actor" => user.ap_id,
+ "cc" => [user.follower_address],
+ "type" => "Update",
+ "to" => [
+ "https://www.w3.org/ns/activitystreams#Public",
+ "https://instance.tld/users/user1",
+ "https://instance.tld/users/user2",
+ "https://instance.tld/users/user3"
+ ],
+ "object" => %{
+ "type" => "Note"
+ }
+ }
+
+ [user: user, message: message, update_message: update_message]
end
setup do: clear_config(:mrf_hellthread)
describe "reject" do
test "rejects the message if the recipient count is above reject_threshold", %{
end
setup do: clear_config(:mrf_hellthread)
describe "reject" do
test "rejects the message if the recipient count is above reject_threshold", %{
+ message: message,
+ update_message: update_message
} do
clear_config([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2})
assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} ==
filter(message)
} do
clear_config([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2})
assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} ==
filter(message)
+
+ assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} ==
+ filter(update_message)
end
test "does not reject the message if the recipient count is below reject_threshold", %{
end
test "does not reject the message if the recipient count is below reject_threshold", %{
+ message: message,
+ update_message: update_message
} do
clear_config([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
assert {:ok, ^message} = filter(message)
} do
clear_config([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
assert {:ok, ^message} = filter(message)
+ assert {:ok, ^update_message} = filter(update_message)
end
end
describe "delist" do
test "delists the message if the recipient count is above delist_threshold", %{
user: user,
end
end
describe "delist" do
test "delists the message if the recipient count is above delist_threshold", %{
user: user,
+ message: message,
+ update_message: update_message
} do
clear_config([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
{:ok, message} = filter(message)
assert user.follower_address in message["to"]
assert "https://www.w3.org/ns/activitystreams#Public" in message["cc"]
} do
clear_config([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
{:ok, message} = filter(message)
assert user.follower_address in message["to"]
assert "https://www.w3.org/ns/activitystreams#Public" in message["cc"]
+
+ {:ok, update_message} = filter(update_message)
+ assert user.follower_address in update_message["to"]
+ assert "https://www.w3.org/ns/activitystreams#Public" in update_message["cc"]
end
test "does not delist the message if the recipient count is below delist_threshold", %{
end
test "does not delist the message if the recipient count is below delist_threshold", %{
+ message: message,
+ update_message: update_message
} do
clear_config([:mrf_hellthread], %{delist_threshold: 4, reject_threshold: 0})
assert {:ok, ^message} = filter(message)
} do
clear_config([:mrf_hellthread], %{delist_threshold: 4, reject_threshold: 0})
assert {:ok, ^message} = filter(message)
+ assert {:ok, ^update_message} = filter(update_message)
- test "excludes follower collection and public URI from threshold count", %{message: message} do
+ test "excludes follower collection and public URI from threshold count", %{
+ message: message,
+ update_message: update_message
+ } do
clear_config([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
assert {:ok, ^message} = filter(message)
clear_config([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
assert {:ok, ^message} = filter(message)
+ assert {:ok, ^update_message} = filter(update_message)
"cc" => ["https://example.com/blocked"]
}
"cc" => ["https://example.com/blocked"]
}
+ update_message = %{
+ "type" => "Update",
+ "to" => ["https://example.com/ok"],
+ "cc" => ["https://example.com/blocked"]
+ }
+
assert MentionPolicy.filter(message) == {:ok, message}
assert MentionPolicy.filter(message) == {:ok, message}
+ assert MentionPolicy.filter(update_message) == {:ok, update_message}
+ update_message = %{
+ "type" => "Update"
+ }
+
assert MentionPolicy.filter(message) == {:ok, message}
assert MentionPolicy.filter(message) == {:ok, message}
+ assert MentionPolicy.filter(update_message) == {:ok, update_message}
"to" => ["https://example.com/ok"]
}
"to" => ["https://example.com/ok"]
}
+ update_message = %{
+ "type" => "Update",
+ "to" => ["https://example.com/ok"]
+ }
+
assert MentionPolicy.filter(message) == {:ok, message}
assert MentionPolicy.filter(message) == {:ok, message}
+ assert MentionPolicy.filter(update_message) == {:ok, update_message}
"cc" => ["https://example.com/ok"]
}
"cc" => ["https://example.com/ok"]
}
+ update_message = %{
+ "type" => "Update",
+ "cc" => ["https://example.com/ok"]
+ }
+
assert MentionPolicy.filter(message) == {:ok, message}
assert MentionPolicy.filter(message) == {:ok, message}
+ assert MentionPolicy.filter(update_message) == {:ok, update_message}
"cc" => ["https://example.com/ok2"]
}
"cc" => ["https://example.com/ok2"]
}
+ update_message = %{
+ "type" => "Update",
+ "to" => ["https://example.com/ok"],
+ "cc" => ["https://example.com/ok2"]
+ }
+
assert MentionPolicy.filter(message) == {:ok, message}
assert MentionPolicy.filter(message) == {:ok, message}
+ assert MentionPolicy.filter(update_message) == {:ok, update_message}
"to" => ["https://example.com/blocked"]
}
"to" => ["https://example.com/blocked"]
}
+ update_message = %{
+ "type" => "Update",
+ "to" => ["https://example.com/blocked"]
+ }
+
assert MentionPolicy.filter(message) ==
{:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
assert MentionPolicy.filter(message) ==
{:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
+
+ assert MentionPolicy.filter(update_message) ==
+ {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
"cc" => ["https://example.com/blocked"]
}
"cc" => ["https://example.com/blocked"]
}
+ update_message = %{
+ "type" => "Update",
+ "to" => ["https://example.com/ok"],
+ "cc" => ["https://example.com/blocked"]
+ }
+
assert MentionPolicy.filter(message) ==
{:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
assert MentionPolicy.filter(message) ==
{:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
+
+ assert MentionPolicy.filter(update_message) ==
+ {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
test "is empty" do
clear_config([:mrf_simple, :media_removal], [])
media_message = build_media_message()
test "is empty" do
clear_config([:mrf_simple, :media_removal], [])
media_message = build_media_message()
+ media_update_message = build_media_update_message()
local_message = build_local_message()
assert SimplePolicy.filter(media_message) == {:ok, media_message}
local_message = build_local_message()
assert SimplePolicy.filter(media_message) == {:ok, media_message}
+ assert SimplePolicy.filter(media_update_message) == {:ok, media_update_message}
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "has a matching host" do
clear_config([:mrf_simple, :media_removal], [{"remote.instance", "Some reason"}])
media_message = build_media_message()
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "has a matching host" do
clear_config([:mrf_simple, :media_removal], [{"remote.instance", "Some reason"}])
media_message = build_media_message()
+ media_update_message = build_media_update_message()
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
media_message
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
media_message
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
+ assert SimplePolicy.filter(media_update_message) ==
+ {:ok,
+ media_update_message
+ |> Map.put("object", Map.delete(media_update_message["object"], "attachment"))}
+
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "match with wildcard domain" do
clear_config([:mrf_simple, :media_removal], [{"*.remote.instance", "Whatever reason"}])
media_message = build_media_message()
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "match with wildcard domain" do
clear_config([:mrf_simple, :media_removal], [{"*.remote.instance", "Whatever reason"}])
media_message = build_media_message()
+ media_update_message = build_media_update_message()
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
media_message
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
media_message
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
+ assert SimplePolicy.filter(media_update_message) ==
+ {:ok,
+ media_update_message
+ |> Map.put("object", Map.delete(media_update_message["object"], "attachment"))}
+
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
end
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
end
test "is empty" do
clear_config([:mrf_simple, :media_nsfw], [])
media_message = build_media_message()
test "is empty" do
clear_config([:mrf_simple, :media_nsfw], [])
media_message = build_media_message()
+ media_update_message = build_media_update_message()
local_message = build_local_message()
assert SimplePolicy.filter(media_message) == {:ok, media_message}
local_message = build_local_message()
assert SimplePolicy.filter(media_message) == {:ok, media_message}
+ assert SimplePolicy.filter(media_update_message) == {:ok, media_update_message}
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "has a matching host" do
clear_config([:mrf_simple, :media_nsfw], [{"remote.instance", "Whetever"}])
media_message = build_media_message()
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "has a matching host" do
clear_config([:mrf_simple, :media_nsfw], [{"remote.instance", "Whetever"}])
media_message = build_media_message()
+ media_update_message = build_media_update_message()
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
{:ok, put_in(media_message, ["object", "sensitive"], true)}
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
{:ok, put_in(media_message, ["object", "sensitive"], true)}
+ assert SimplePolicy.filter(media_update_message) ==
+ {:ok, put_in(media_update_message, ["object", "sensitive"], true)}
+
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "match with wildcard domain" do
clear_config([:mrf_simple, :media_nsfw], [{"*.remote.instance", "yeah yeah"}])
media_message = build_media_message()
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
test "match with wildcard domain" do
clear_config([:mrf_simple, :media_nsfw], [{"*.remote.instance", "yeah yeah"}])
media_message = build_media_message()
+ media_update_message = build_media_update_message()
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
{:ok, put_in(media_message, ["object", "sensitive"], true)}
local_message = build_local_message()
assert SimplePolicy.filter(media_message) ==
{:ok, put_in(media_message, ["object", "sensitive"], true)}
+ assert SimplePolicy.filter(media_update_message) ==
+ {:ok, put_in(media_update_message, ["object", "sensitive"], true)}
+
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
end
assert SimplePolicy.filter(local_message) == {:ok, local_message}
end
end
+ defp build_media_update_message do
+ %{
+ "actor" => "https://remote.instance/users/bob",
+ "type" => "Update",
+ "object" => %{
+ "attachment" => [%{}],
+ "tag" => ["foo"],
+ "sensitive" => false
+ }
+ }
+ end
+
describe "when :report_removal" do
test "is empty" do
clear_config([:mrf_simple, :report_removal], [])
describe "when :report_removal" do
test "is empty" do
clear_config([:mrf_simple, :report_removal], [])