Merge branch 'tests/mrf_policy' into 'develop'
tests MRF filters See merge request pleroma/pleroma!1379
This commit is contained in:
commit
37b0bd0d86
|
@ -9,8 +9,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
|
||||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
@reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless])
|
@reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless])
|
||||||
|
|
||||||
def filter_by_summary(
|
def filter_by_summary(
|
||||||
%{"summary" => parent_summary} = _parent,
|
%{data: %{"summary" => parent_summary}} = _in_reply_to,
|
||||||
%{"summary" => child_summary} = child
|
%{"summary" => child_summary} = child
|
||||||
)
|
)
|
||||||
when not is_nil(child_summary) and byte_size(child_summary) > 0 and
|
when not is_nil(child_summary) and byte_size(child_summary) > 0 and
|
||||||
|
@ -24,17 +25,13 @@ def filter_by_summary(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_by_summary(_parent, child), do: child
|
def filter_by_summary(_in_reply_to, child), do: child
|
||||||
|
|
||||||
def filter(%{"type" => activity_type} = object) when activity_type == "Create" do
|
|
||||||
child = object["object"]
|
|
||||||
in_reply_to = Object.normalize(child["inReplyTo"])
|
|
||||||
|
|
||||||
|
def filter(%{"type" => "Create", "object" => child_object} = object) do
|
||||||
child =
|
child =
|
||||||
if(in_reply_to,
|
child_object["inReplyTo"]
|
||||||
do: filter_by_summary(in_reply_to.data, child),
|
|> Object.normalize(child_object["inReplyTo"])
|
||||||
else: child
|
|> filter_by_summary(child_object)
|
||||||
)
|
|
||||||
|
|
||||||
object = Map.put(object, "object", child)
|
object = Map.put(object, "object", child)
|
||||||
|
|
||||||
|
|
|
@ -10,19 +10,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
|
||||||
def filter(
|
def filter(
|
||||||
%{
|
%{
|
||||||
"type" => "Create",
|
"type" => "Create",
|
||||||
"object" => %{"content" => content, "attachment" => _attachment} = child_object
|
"object" => %{"content" => content, "attachment" => _} = _child_object
|
||||||
} = object
|
} = object
|
||||||
)
|
)
|
||||||
when content in [".", "<p>.</p>"] do
|
when content in [".", "<p>.</p>"] do
|
||||||
child_object =
|
{:ok, put_in(object, ["object", "content"], "")}
|
||||||
child_object
|
|
||||||
|> Map.put("content", "")
|
|
||||||
|
|
||||||
object =
|
|
||||||
object
|
|
||||||
|> Map.put("object", child_object)
|
|
||||||
|
|
||||||
{:ok, object}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
|
@ -8,18 +8,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
|
||||||
|
|
||||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
def filter(%{"type" => activity_type} = object) when activity_type == "Create" do
|
def filter(%{"type" => "Create", "object" => child_object} = object) do
|
||||||
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
|
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
|
||||||
|
|
||||||
child = object["object"]
|
|
||||||
|
|
||||||
content =
|
content =
|
||||||
child["content"]
|
child_object["content"]
|
||||||
|> HTML.filter_tags(scrub_policy)
|
|> HTML.filter_tags(scrub_policy)
|
||||||
|
|
||||||
child = Map.put(child, "content", content)
|
object = put_in(object, ["object", "content"], content)
|
||||||
|
|
||||||
object = Map.put(object, "object", child)
|
|
||||||
|
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,46 +3,42 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
|
defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
|
||||||
alias Pleroma.User
|
|
||||||
@moduledoc "Rejects non-public (followers-only, direct) activities"
|
@moduledoc "Rejects non-public (followers-only, direct) activities"
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
|
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def filter(%{"type" => "Create"} = object) do
|
def filter(%{"type" => "Create"} = object) do
|
||||||
user = User.get_cached_by_ap_id(object["actor"])
|
user = User.get_cached_by_ap_id(object["actor"])
|
||||||
public = "https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
|
|
||||||
# Determine visibility
|
# Determine visibility
|
||||||
visibility =
|
visibility =
|
||||||
cond do
|
cond do
|
||||||
public in object["to"] -> "public"
|
@public in object["to"] -> "public"
|
||||||
public in object["cc"] -> "unlisted"
|
@public in object["cc"] -> "unlisted"
|
||||||
user.follower_address in object["to"] -> "followers"
|
user.follower_address in object["to"] -> "followers"
|
||||||
true -> "direct"
|
true -> "direct"
|
||||||
end
|
end
|
||||||
|
|
||||||
policy = Pleroma.Config.get(:mrf_rejectnonpublic)
|
policy = Config.get(:mrf_rejectnonpublic)
|
||||||
|
|
||||||
case visibility do
|
cond do
|
||||||
"public" ->
|
visibility in ["public", "unlisted"] ->
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
|
|
||||||
"unlisted" ->
|
visibility == "followers" and Keyword.get(policy, :allow_followersonly) ->
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
|
|
||||||
"followers" ->
|
visibility == "direct" and Keyword.get(policy, :allow_direct) ->
|
||||||
with true <- Keyword.get(policy, :allow_followersonly) do
|
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
else
|
|
||||||
_e -> {:reject, nil}
|
|
||||||
end
|
|
||||||
|
|
||||||
"direct" ->
|
true ->
|
||||||
with true <- Keyword.get(policy, :allow_direct) do
|
{:reject, nil}
|
||||||
{:ok, object}
|
|
||||||
else
|
|
||||||
_e -> {:reject, nil}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
||||||
- `mrf_tag:disable-any-subscription`: Reject any follow requests
|
- `mrf_tag:disable-any-subscription`: Reject any follow requests
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
|
defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
|
||||||
defp get_tags(_), do: []
|
defp get_tags(_), do: []
|
||||||
|
|
||||||
defp process_tag(
|
defp process_tag(
|
||||||
"mrf_tag:media-force-nsfw",
|
"mrf_tag:media-force-nsfw",
|
||||||
%{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
|
%{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"attachment" => child_attachment} = object
|
||||||
|
} = message
|
||||||
)
|
)
|
||||||
when length(child_attachment) > 0 do
|
when length(child_attachment) > 0 do
|
||||||
tags = (object["tag"] || []) ++ ["nsfw"]
|
tags = (object["tag"] || []) ++ ["nsfw"]
|
||||||
|
@ -41,7 +46,10 @@ defp process_tag(
|
||||||
|
|
||||||
defp process_tag(
|
defp process_tag(
|
||||||
"mrf_tag:media-strip",
|
"mrf_tag:media-strip",
|
||||||
%{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
|
%{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"attachment" => child_attachment} = object
|
||||||
|
} = message
|
||||||
)
|
)
|
||||||
when length(child_attachment) > 0 do
|
when length(child_attachment) > 0 do
|
||||||
object = Map.delete(object, "attachment")
|
object = Map.delete(object, "attachment")
|
||||||
|
@ -52,19 +60,22 @@ defp process_tag(
|
||||||
|
|
||||||
defp process_tag(
|
defp process_tag(
|
||||||
"mrf_tag:force-unlisted",
|
"mrf_tag:force-unlisted",
|
||||||
%{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
|
%{
|
||||||
|
"type" => "Create",
|
||||||
|
"to" => to,
|
||||||
|
"cc" => cc,
|
||||||
|
"actor" => actor,
|
||||||
|
"object" => object
|
||||||
|
} = message
|
||||||
) do
|
) do
|
||||||
user = User.get_cached_by_ap_id(actor)
|
user = User.get_cached_by_ap_id(actor)
|
||||||
|
|
||||||
if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") do
|
if Enum.member?(to, @public) do
|
||||||
to =
|
to = List.delete(to, @public) ++ [user.follower_address]
|
||||||
List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
|
cc = List.delete(cc, user.follower_address) ++ [@public]
|
||||||
|
|
||||||
cc =
|
|
||||||
List.delete(cc, user.follower_address) ++ ["https://www.w3.org/ns/activitystreams#Public"]
|
|
||||||
|
|
||||||
object =
|
object =
|
||||||
message["object"]
|
object
|
||||||
|> Map.put("to", to)
|
|> Map.put("to", to)
|
||||||
|> Map.put("cc", cc)
|
|> Map.put("cc", cc)
|
||||||
|
|
||||||
|
@ -82,19 +93,22 @@ defp process_tag(
|
||||||
|
|
||||||
defp process_tag(
|
defp process_tag(
|
||||||
"mrf_tag:sandbox",
|
"mrf_tag:sandbox",
|
||||||
%{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
|
%{
|
||||||
|
"type" => "Create",
|
||||||
|
"to" => to,
|
||||||
|
"cc" => cc,
|
||||||
|
"actor" => actor,
|
||||||
|
"object" => object
|
||||||
|
} = message
|
||||||
) do
|
) do
|
||||||
user = User.get_cached_by_ap_id(actor)
|
user = User.get_cached_by_ap_id(actor)
|
||||||
|
|
||||||
if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") or
|
if Enum.member?(to, @public) or Enum.member?(cc, @public) do
|
||||||
Enum.member?(cc, "https://www.w3.org/ns/activitystreams#Public") do
|
to = List.delete(to, @public) ++ [user.follower_address]
|
||||||
to =
|
cc = List.delete(cc, @public)
|
||||||
List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
|
|
||||||
|
|
||||||
cc = List.delete(cc, "https://www.w3.org/ns/activitystreams#Public")
|
|
||||||
|
|
||||||
object =
|
object =
|
||||||
message["object"]
|
object
|
||||||
|> Map.put("to", to)
|
|> Map.put("to", to)
|
||||||
|> Map.put("cc", cc)
|
|> Map.put("cc", cc)
|
||||||
|
|
||||||
|
@ -123,7 +137,8 @@ defp process_tag(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}), do: {:reject, nil}
|
defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}),
|
||||||
|
do: {:reject, nil}
|
||||||
|
|
||||||
defp process_tag(_, message), do: {:ok, message}
|
defp process_tag(_, message), do: {:ok, message}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,12 @@ defp filter_by_list(%{"actor" => actor} = object, allow_list) do
|
||||||
@impl true
|
@impl true
|
||||||
def filter(%{"actor" => actor} = object) do
|
def filter(%{"actor" => actor} = object) do
|
||||||
actor_info = URI.parse(actor)
|
actor_info = URI.parse(actor)
|
||||||
allow_list = Config.get([:mrf_user_allowlist, String.to_atom(actor_info.host)], [])
|
|
||||||
|
allow_list =
|
||||||
|
Config.get(
|
||||||
|
[:mrf_user_allowlist, String.to_atom(actor_info.host)],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
filter_by_list(object, allow_list)
|
filter_by_list(object, allow_list)
|
||||||
end
|
end
|
1
mix.lock
1
mix.lock
|
@ -76,6 +76,7 @@
|
||||||
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
|
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
|
||||||
"recon": {:git, "https://github.com/ferd/recon.git", "75d70c7c08926d2f24f1ee6de14ee50fe8a52763", [tag: "2.4.0"]},
|
"recon": {:git, "https://github.com/ferd/recon.git", "75d70c7c08926d2f24f1ee6de14ee50fe8a52763", [tag: "2.4.0"]},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
|
||||||
|
"stream_data": {:hex, :stream_data, "0.4.3", "62aafd870caff0849a5057a7ec270fad0eb86889f4d433b937d996de99e3db25", [:mix], [], "hexpm"},
|
||||||
"swoosh": {:hex, :swoosh, "0.20.0", "9a6c13822c9815993c03b6f8fccc370fcffb3c158d9754f67b1fdee6b3a5d928", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.12", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
|
"swoosh": {:hex, :swoosh, "0.20.0", "9a6c13822c9815993c03b6f8fccc370fcffb3c158d9754f67b1fdee6b3a5d928", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.12", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
|
"syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
|
||||||
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
|
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
|
||||||
|
|
||||||
|
describe "rewrites summary" do
|
||||||
|
test "it adds `re:` to summary object when child summary and parent summary equal" do
|
||||||
|
message = %{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{
|
||||||
|
"summary" => "object-summary",
|
||||||
|
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||||
|
assert res["object"]["summary"] == "re: object-summary"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it adds `re:` to summary object when child summary containts re-subject of parent summary " do
|
||||||
|
message = %{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{
|
||||||
|
"summary" => "object-summary",
|
||||||
|
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "re: object-summary"}}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||||
|
assert res["object"]["summary"] == "re: object-summary"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "skip filter" do
|
||||||
|
test "it skip if type isn't 'Create'" do
|
||||||
|
message = %{
|
||||||
|
"type" => "Annotation",
|
||||||
|
"object" => %{"summary" => "object-summary"}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||||
|
assert res == message
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it skip if summary is empty" do
|
||||||
|
message = %{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{
|
||||||
|
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||||
|
assert res == message
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it skip if inReplyTo is empty" do
|
||||||
|
message = %{"type" => "Create", "object" => %{"summary" => "summary"}}
|
||||||
|
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||||
|
assert res == message
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it skip if parent and child summary isn't equal" do
|
||||||
|
message = %{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{
|
||||||
|
"summary" => "object-summary",
|
||||||
|
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||||
|
assert res == message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
|
||||||
|
|
||||||
|
test "it clears content object" do
|
||||||
|
message = %{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"content" => ".", "attachment" => "image"}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
|
||||||
|
assert res["object"]["content"] == ""
|
||||||
|
|
||||||
|
message = put_in(message, ["object", "content"], "<p>.</p>")
|
||||||
|
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
|
||||||
|
assert res["object"]["content"] == ""
|
||||||
|
end
|
||||||
|
|
||||||
|
@messages [
|
||||||
|
%{
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"content" => "test", "attachment" => "image"}
|
||||||
|
},
|
||||||
|
%{"type" => "Create", "object" => %{"content" => "."}},
|
||||||
|
%{"type" => "Create", "object" => %{"content" => "<p>.</p>"}}
|
||||||
|
]
|
||||||
|
test "it skips filter" do
|
||||||
|
Enum.each(@messages, fn message ->
|
||||||
|
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
|
||||||
|
assert res == message
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
|
||||||
|
|
||||||
|
@html_sample """
|
||||||
|
<b>this is in bold</b>
|
||||||
|
<p>this is a paragraph</p>
|
||||||
|
this is a linebreak<br />
|
||||||
|
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||||
|
this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a>
|
||||||
|
this is an image: <img src="http://example.com/image.jpg"><br />
|
||||||
|
<script>alert('hacked')</script>
|
||||||
|
"""
|
||||||
|
|
||||||
|
test "it filter html tags" do
|
||||||
|
expected = """
|
||||||
|
<b>this is in bold</b>
|
||||||
|
<p>this is a paragraph</p>
|
||||||
|
this is a linebreak<br />
|
||||||
|
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||||
|
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
||||||
|
this is an image: <img src="http://example.com/image.jpg" /><br />
|
||||||
|
alert('hacked')
|
||||||
|
"""
|
||||||
|
|
||||||
|
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
|
||||||
|
|
||||||
|
assert {:ok, res} = NormalizeMarkup.filter(message)
|
||||||
|
assert res["object"]["content"] == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it skips filter if type isn't `Create`" do
|
||||||
|
message = %{"type" => "Note", "object" => %{}}
|
||||||
|
|
||||||
|
assert {:ok, res} = NormalizeMarkup.filter(message)
|
||||||
|
assert res == message
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,105 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic
|
||||||
|
|
||||||
|
setup do
|
||||||
|
policy = Pleroma.Config.get([:mrf_rejectnonpublic])
|
||||||
|
on_exit(fn -> Pleroma.Config.put([:mrf_rejectnonpublic], policy) end)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "public message" do
|
||||||
|
test "it's allowed when address is public" do
|
||||||
|
actor = insert(:user, follower_address: "test-address")
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
|
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"type" => "Create"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it's allowed when cc address contain public address" do
|
||||||
|
actor = insert(:user, follower_address: "test-address")
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
|
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"type" => "Create"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "followers message" do
|
||||||
|
test "it's allowed when addrer of message in the follower addresses of user and it enabled in config" do
|
||||||
|
actor = insert(:user, follower_address: "test-address")
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"to" => ["test-address"],
|
||||||
|
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"type" => "Create"
|
||||||
|
}
|
||||||
|
|
||||||
|
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], true)
|
||||||
|
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it's rejected when addrer of message in the follower addresses of user and it disabled in config" do
|
||||||
|
actor = insert(:user, follower_address: "test-address")
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"to" => ["test-address"],
|
||||||
|
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"type" => "Create"
|
||||||
|
}
|
||||||
|
|
||||||
|
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false)
|
||||||
|
assert {:reject, nil} = RejectNonPublic.filter(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "direct message" do
|
||||||
|
test "it's allows when direct messages are allow" do
|
||||||
|
actor = insert(:user)
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"to" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"type" => "Create"
|
||||||
|
}
|
||||||
|
|
||||||
|
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], true)
|
||||||
|
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it's reject when direct messages aren't allow" do
|
||||||
|
actor = insert(:user)
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"to" => ["https://www.w3.org/ns/activitystreams#Publid~~~"],
|
||||||
|
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||||
|
"type" => "Create"
|
||||||
|
}
|
||||||
|
|
||||||
|
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false)
|
||||||
|
assert {:reject, nil} = RejectNonPublic.filter(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,123 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.TagPolicy
|
||||||
|
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
|
describe "mrf_tag:disable-any-subscription" do
|
||||||
|
test "rejects message" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"])
|
||||||
|
message = %{"object" => actor.ap_id, "type" => "Follow"}
|
||||||
|
assert {:reject, nil} = TagPolicy.filter(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "mrf_tag:disable-remote-subscription" do
|
||||||
|
test "rejects non-local follow requests" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
|
||||||
|
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)
|
||||||
|
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
|
||||||
|
assert {:reject, nil} = TagPolicy.filter(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "allows non-local follow requests" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
|
||||||
|
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: true)
|
||||||
|
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
|
||||||
|
assert {:ok, message} = TagPolicy.filter(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "mrf_tag:sandbox" do
|
||||||
|
test "removes from public timelines" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:sandbox"])
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{},
|
||||||
|
"to" => [@public, "f"],
|
||||||
|
"cc" => [@public, "d"]
|
||||||
|
}
|
||||||
|
|
||||||
|
except_message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d"]},
|
||||||
|
"to" => ["f", actor.follower_address],
|
||||||
|
"cc" => ["d"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "mrf_tag:force-unlisted" do
|
||||||
|
test "removes from the federated timeline" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:force-unlisted"])
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{},
|
||||||
|
"to" => [@public, "f"],
|
||||||
|
"cc" => [actor.follower_address, "d"]
|
||||||
|
}
|
||||||
|
|
||||||
|
except_message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
|
||||||
|
"to" => ["f", actor.follower_address],
|
||||||
|
"cc" => ["d", @public]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "mrf_tag:media-strip" do
|
||||||
|
test "removes attachments" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:media-strip"])
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"attachment" => ["file1"]}
|
||||||
|
}
|
||||||
|
|
||||||
|
except_message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "mrf_tag:media-force-nsfw" do
|
||||||
|
test "Mark as sensitive on presence of attachments" do
|
||||||
|
actor = insert(:user, tags: ["mrf_tag:media-force-nsfw"])
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"tag" => ["test"], "attachment" => ["file1"]}
|
||||||
|
}
|
||||||
|
|
||||||
|
except_message = %{
|
||||||
|
"actor" => actor.ap_id,
|
||||||
|
"type" => "Create",
|
||||||
|
"object" => %{"tag" => ["test", "nsfw"], "attachment" => ["file1"], "sensitive" => true}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
|
||||||
|
|
||||||
|
setup do
|
||||||
|
policy = Pleroma.Config.get([:mrf_user_allowlist]) || []
|
||||||
|
on_exit(fn -> Pleroma.Config.put([:mrf_user_allowlist], policy) end)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "pass filter if allow list is empty" do
|
||||||
|
actor = insert(:user)
|
||||||
|
message = %{"actor" => actor.ap_id}
|
||||||
|
assert UserAllowListPolicy.filter(message) == {:ok, message}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "pass filter if allow list isn't empty and user in allow list" do
|
||||||
|
actor = insert(:user)
|
||||||
|
Pleroma.Config.put([:mrf_user_allowlist, :localhost], [actor.ap_id, "test-ap-id"])
|
||||||
|
message = %{"actor" => actor.ap_id}
|
||||||
|
assert UserAllowListPolicy.filter(message) == {:ok, message}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejected if allow list isn't empty and user not in allow list" do
|
||||||
|
actor = insert(:user)
|
||||||
|
Pleroma.Config.put([:mrf_user_allowlist, :localhost], ["test-ap-id"])
|
||||||
|
message = %{"actor" => actor.ap_id}
|
||||||
|
assert UserAllowListPolicy.filter(message) == {:reject, nil}
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue